Compare commits

..

120 Commits

Author SHA1 Message Date
DennisSchiefer fb995ad0b0 small UI move 2012-04-16 10:26:10 +01:00
DennisSchiefer 3a85661e45 fixed bugs with IE 2012-04-16 10:23:31 +01:00
DennisSchiefer 23ca80030e disabled printing for this release 2012-04-15 19:35:50 +02:00
DennisSchiefer f08c389faa moved version to 0.1.4 2012-04-15 19:35:26 +02:00
DennisSchiefer 47369a0036 continued work on printing support 2012-04-15 19:34:18 +02:00
DennisSchiefer 253b591a87 fixed error with translation of east to German 2012-04-15 19:33:23 +02:00
DennisSchiefer 5c4488d350 removed fixed with from input boxes 2012-04-15 19:32:41 +02:00
DennisSchiefer 25310ff1bd corrected error in via computation when no road was visible 2012-04-15 19:31:49 +02:00
DennisSchiefer c2d52080d3 use geocode even if no route is found 2012-04-14 18:49:28 +02:00
DennisSchiefer bf681855ed moved list of supported languages and tileservers to config file 2012-04-14 18:26:32 +02:00
DennisSchiefer 899d216b9b made it easier to remove localization and on-demand loading of new
language packs,
added parameter to say whether to use on-demand reloading,
added parameter for the directory that contains the localization files,
corrected a small bug when the string for the HEAD_ON instruction was
not available,
2012-04-14 18:03:33 +02:00
DennisSchiefer 73aeab3a57 reworked loading of images and icons (-> easier to add new ones),
adapted routing description to use new description ids,
fixed bug with localization dropdown and FF3,
added localization for "(found X results)"
2012-04-13 17:47:53 +01:00
DennisSchiefer 61073ebc9d added newline to readme 2012-04-12 22:52:18 +02:00
DennisSchiefer 393334cabd corrected error in route description,
made dropdown button more beautiful
2012-04-12 22:44:30 +02:00
DennisSchiefer 01e4afe2f0 changed legal string in html file 2012-04-11 23:07:00 +02:00
DennisSchiefer 9b599c90f8 Merge branch 'trial/printing' into develop
Conflicts:
	WebContent/OSRM.debug.js
2012-04-11 23:03:24 +02:00
DennisSchiefer 252c234221 made parsing of get parameters more robust 2012-04-11 22:59:41 +02:00
DennisSchiefer 888a5d04c8 removal of dragger marker more consistent,
changed printing initialization to be more easily removable from GUI,
localization bug fixes,
added option to give language as get parameter (hl=),
2012-04-11 22:00:19 +02:00
DennisSchiefer b1631eff77 more localization,
fixed bugs with FF3
2012-04-11 17:31:02 +01:00
DennisSchiefer ffd5e2de99 all images are now loaded in main.js 2012-04-10 23:50:04 +02:00
DennisSchiefer ea207cef6e improved language support: geocoding uses language settings, geocoding
results & locations are also translated if possible
2012-04-10 21:47:30 +02:00
DennisSchiefer 893c09f6fc Merge remote-tracking branch 'origin/trial/printing' into trial/printing
Conflicts:
	WebContent/OSRM.GUI.js
2012-04-09 22:35:47 +02:00
shiin 213bb71b35 changed behaviour of geocoder (return always triggers geocoder, moving a
single marker clears search results)
2012-04-09 11:59:32 +02:00
shiin 0fd8d4d8cf all visible lat/lng coordinates are truncated after 6 digits (this
includes inputboxes, osmbugs link, route link, gpx link),
moved all events from html to javascript
2012-04-08 19:50:30 +02:00
shiin 13f0a3fb6b redid html and css,
switched to sans-serif font
2012-04-08 12:02:36 +02:00
shiin 3141d3ba48 prepared localization / route description module to use description ids
instead of description strings
2012-04-06 12:27:23 +02:00
DennisSchiefer 4ff4fcf516 corrected bug in reverse geocoder timeout handler 2012-04-05 09:08:41 +02:00
DennisSchiefer f273f0cfc5 drag marker can no longer be removed by clicking on it 2012-04-05 09:04:48 +02:00
DennisSchiefer dc192d47a8 input boxes are no longer deleted on language change 2012-04-05 01:12:15 +02:00
DennisSchiefer 0f032f7635 bugfix, so that markers will use correct mousepointer again 2012-04-04 15:40:16 +02:00
DennisSchiefer 060c7e499a added bugtracker URL to readme 2012-04-04 15:11:38 +02:00
DennisSchiefer 28a241c371 more testing on printing 2012-04-04 13:08:25 +02:00
DennisSchiefer bab2887f8f Merge branch 'trial/dragging' into develop
Conflicts:
	WebContent/OSRM.JSONP.js
	WebContent/OSRM.debug.js
	WebContent/main.html
2012-04-03 21:30:35 +02:00
DennisSchiefer abba49a44e - added GUI support for language switching
- first tests for support of printing
2012-04-03 21:13:44 +02:00
DennisSchiefer 4638e7c24d corrected error and bumped version to 0.1.3 2012-04-02 20:57:39 +02:00
DennisSchiefer fe420e5bfc added buttons to delete source and target 2012-04-02 08:54:25 +02:00
DennisSchiefer 93ae928236 added icons that can change their image,
added image change while dragging markers,
increased (invisible) size of drag marker,
fixed issues with drag marker and highlight marker overlapping
2012-04-02 08:29:03 +02:00
DennisSchiefer 3b485f1426 finished dragging of routes,
moved corrected bugs in Leaflet to their own file
(drag after dragend, distance to path),
open osmbugs in new window
2012-04-01 19:13:54 +02:00
DennisSchiefer 5165e01a5c added draggable routes,
changed findViaPosition to only return the index and not set the node,
IMPORTANT: changed leaflet-src.js for a bugfix!,
2012-03-30 16:30:16 +01:00
DennisSchiefer 7b4e923ec4 added option (commented out) to use input box for route links to get
a marked url when clicking in it -> test what is better
2012-03-30 10:35:14 +01:00
DennisSchiefer 007dd19cec added buttons to switch to JOSM and OSM Bugs,
added getCenter function that respects UI visibility
2012-03-30 10:10:51 +01:00
DennisSchiefer fd3cf02af4 complete restructure of OSRM.Routing 2012-03-29 16:55:12 +01:00
DennisSchiefer 2bb51717b9 extracted OSRM.Map and OSRM.MapView classes,
moved centering that respects UI visibility to OSRM.MapView
2012-03-29 14:34:55 +01:00
DennisSchiefer 4fe6346146 reordered styles in main.html,
readded default values to GUI,
made TODO marker to check whether GUI is initilaized
2012-03-28 15:02:09 +01:00
DennisSchiefer c5bd2b0b1d renamed routing.js,
encapsulated local helper functions in OSRM.base
2012-03-28 14:30:26 +01:00
DennisSchiefer 71426cf760 changed OSRM debug to work with IE6,
deactivated JSONP timing routines
2012-03-28 14:06:18 +01:00
DennisSchiefer 0ab287e707 modified JSONP statistics,
rearranged OSRM debug so that it works in IE
2012-03-28 13:59:39 +01:00
DennisSchiefer 49cc0bfb09 added functions to test JSONP timings 2012-03-28 13:01:26 +01:00
DennisSchiefer e132ac5c53 moved routing functions to OSRM namespace,
added functions to measure JSONP timings
2012-03-28 12:57:42 +01:00
DennisSchiefer 1a9776cff9 moved utils into OSRM namespace 2012-03-28 12:17:22 +01:00
DennisSchiefer 342a0d22bd - removed bug in centering routes when UI was hidden
- moved all browser dependencies to OSRM.Browser
- refactored via code to use Leaflet functions
- added function to extract route layerPoints
2012-03-28 10:51:54 +01:00
DennisSchiefer 251a43980a switched to Markdown readme 2012-03-26 16:47:40 +01:00
DennisSchiefer 41ba8b5e3e next try 2012-03-26 14:28:38 +01:00
DennisSchiefer 30df2aae10 Do inline links now work with Github asciidoc renderer? 2012-03-26 14:27:18 +01:00
DennisSchiefer a6f00b1856 yet another version 2012-03-26 14:15:44 +01:00
DennisSchiefer af26c47052 GitHUB didn't like my asciidoc... 2012-03-26 14:01:53 +01:00
DennisSchiefer 0a774aeef2 Changed name of README 2012-03-26 13:58:32 +01:00
DennisSchiefer a89aa68686 added README 2012-03-26 13:53:39 +01:00
DennisSchiefer 4b93107415 made logo a bit smaller so that it is centered,
removing source or target now clears route description,
changed GUI handling to no longer be dependent on the actual width of
the sidebar
2012-03-23 18:13:07 +01:00
DennisSchiefer e0602934b2 Refactored Geocoder -> now resides in OSRM namespace 2012-03-23 09:55:55 +01:00
DennisSchiefer fdace26222 changed getPosition().lat / .lng to getLat(), getLng() 2012-03-22 18:31:35 +01:00
DennisSchiefer bef41ed667 geocoder error messages now state the input string,
website is XHTML1.0 strict compliant,
centering now respects if the sidebar is shown,
corrected spelling mistakes
2012-03-22 17:35:09 +01:00
DennisSchiefer 4e2e95cc27 version and date is now taken from OSRM.base,
when source/target markers are deleted the inputbox is emptied
2012-03-19 17:09:03 +01:00
DennisSchiefer f4c6ec90ce fix to route link generator and parser 2012-03-19 10:28:32 +01:00
DennisSchiefer eed22b343a more geocoder refactoring 2012-03-18 22:17:59 +01:00
DennisSchiefer 08ce748a37 removed dirty flags 2012-03-18 22:00:29 +01:00
DennisSchiefer 69790eb8c7 refactored geocoder code (still need to check dirty flags) 2012-03-18 21:44:14 +01:00
DennisSchiefer 97b9c65c97 refactored reverse geocoder 2012-03-18 20:03:15 +01:00
DennisSchiefer 92dbadebae increased zoom level for route description (new config entry),
removed some deprecated comments
2012-03-18 18:17:04 +01:00
DennisSchiefer fe6d854e11 improved handling of dragging,
link to route gui improved,
JSONP can now take parameters
2012-03-18 17:42:05 +01:00
DennisSchiefer 4615b01fdf moved inputbox logic to javascript file,
corrected error with second ENTER not being registered
2012-03-18 15:04:17 +01:00
DennisSchiefer 276b023b05 changed checking if eventhandler storage exists 2012-03-18 12:29:02 +01:00
DennisSchiefer 350cacb2f3 added try-finally guards to JSONP calls 2012-03-18 11:38:21 +01:00
DennisSchiefer 25ec6105c5 reverse geocoding now always shows two information if possible 2012-03-17 22:26:57 +01:00
DennisSchiefer 3e4249ad41 used abbreviations for sub-namespaces GLOBALS, CONSTANTS 2012-03-17 20:49:19 +01:00
DennisSchiefer 13126ac0c1 moved all variables/objects to OSRM namespace 2012-03-17 20:43:52 +01:00
DennisSchiefer d51aee4fbe bugfix to route link storing map view location 2012-03-17 17:07:34 +01:00
DennisSchiefer f9877fd8ba refactoring: used hasSource, hasTarget routines throughout the code 2012-03-17 17:04:45 +01:00
DennisSchiefer a39a35df73 moved leaflet.ie.css to new position 2012-03-17 15:48:24 +01:00
DennisSchiefer 2670dd68f3 added event handler base class 2012-03-17 15:28:27 +01:00
DennisSchiefer 9adb590ce7 added OSRM.CONSTANTS, OSRM.GLOBALS for better structuring,
improved comments in OSRM.base.js and OSRM.config.js
2012-03-17 14:45:04 +01:00
DennisSchiefer 9567a7e38c added support for saving route zoom level and position in route links 2012-03-17 14:17:08 +01:00
DennisSchiefer d86eaa00a0 compressed target.png 2012-03-16 18:27:52 +01:00
DennisSchiefer 54c0d50b68 reseting now also resets OSRM.JSONP 2012-03-16 17:52:10 +01:00
DennisSchiefer 204189c326 - version bump to v0.1.1
- restructured buttons (route is gone, search is show)
- added prefetching gui hide/show buttons
- increased timeout to 5000ms
- click highlight marker to hide it
- boundary box on Europe when querying geocoder
- added "reached your destination" display in route instructions
- improved visual for route summary
- when loading a stored route, source and target are named and the route
is zoomed correctly
- improved display results of reverse geocoder (ues village/country
tags)
- more consistent behaviour when displaying reverse geocoder results
or geocoordinates
- reverse geocoder now works at dragend
- more consistent behaviour when leaving an input box
- reversing a route when only one marker is set empties the result box
2012-03-16 15:06:43 +01:00
DennisSchiefer acdfa546a8 added more precise distance values (at least three digits of precision) 2012-03-16 10:41:54 +01:00
DennisSchiefer 6a9216d6e4 added functions to check whether source or target exists,
readded routing button
2012-03-16 09:42:14 +01:00
DennisSchiefer 9c2a1dc37f implemented several security measures when parsing GET input to the site 2012-03-16 09:07:03 +01:00
DennisSchiefer 26c9d357f0 made reverse geocoding more intuitive,
changed search and route buttons to centering buttons
2012-03-16 07:22:47 +01:00
DennisSchiefer 879d73c629 testing to remove route button -> search will be automatical on lost
focus
2012-03-15 17:45:22 +01:00
DennisSchiefer 441146eeae changed look of route description header area 2012-03-15 17:42:17 +01:00
DennisSchiefer d453cadc8c added call option to set destination when calling the site 2012-03-15 14:22:00 +01:00
DennisSchiefer 74188206e8 website url is now retrieved directly from browser,
removed unneeded localization strings
2012-03-15 14:01:34 +01:00
DennisSchiefer 700206099b made route reset more robust by clearing *really* everything,
improved route description (added distances to the right, bold street
names, orientation in first instruction and non-breaking spaces for
units),
route link now displays the shortened link name,
content of input boxes is only overwritten if the respective node is
set or dragged,
experimental support for reverse geocoding (when setting a new node by
text box or clicking on map)
2012-03-15 13:29:28 +01:00
DennisSchiefer aa952df541 added favicon,
removed commata that IE was complaining about
2012-03-15 09:05:00 +01:00
DennisSchiefer b8944da9dc prevent browser context menu on map 2012-03-14 18:07:15 +01:00
DennisSchiefer 22dda2b285 added new gui buttons for opening/closing,
route button now works,
more precise error message when geocoder does not find a result,
added maximum input length for text boxes
2012-03-14 17:42:14 +01:00
DennisSchiefer 0ee469c4e0 Merge branch 'develop' of
https://DennisSchiefer@bitbucket.org/DennisSchiefer/project-osrm-web.git
into develop

Conflicts:
	WebContent/routing.js
2012-03-14 16:50:14 +01:00
DennisSchiefer a7eef27e99 added legal headers,
beautified comments,
moved language settings to config,
moved timeout settings to config,
corrected bug with route link and via nodes,
removed old files,
corrected spelling error for roundabout
2012-03-14 16:45:15 +01:00
DennisSchiefer 4b40f1253f added legal headers,
beautified comments,
moved language settings to config,
moved timeout settings to config,
corrected bug with route link and via nodes
removed old files
2012-03-14 16:30:11 +01:00
DennisSchiefer 5ebe8080f9 small bug class/id mixed up 2012-03-14 11:24:40 +01:00
DennisSchiefer d92b28d2c3 restructured for release 2012-03-14 10:39:37 +01:00
DennisSchiefer ec27881f39 test fencing 2012-03-13 22:39:28 +01:00
DennisSchiefer c5a8ec7c31 added better lat/lng display when dragging,
added experimental faster route redraw (commented out),
changed default website url and routing url,
removed drag after dragend event workaround
2012-03-13 22:25:40 +01:00
DennisSchiefer afbd3347da added clear debug log button,
removed showing of links in gpx, route requests,
checked html with validator
2012-03-13 20:51:44 +01:00
DennisSchiefer 41bcafc3a1 added lat/lng processing 2012-03-13 17:57:48 +01:00
DennisSchiefer 27d24885a9 debug window stays at botoom when adding data 2012-03-13 17:36:40 +01:00
DennisSchiefer 805402b230 starting to reverse geocoding 2012-03-13 17:32:18 +01:00
DennisSchiefer 4918549bac fixed bug when selecting city options in geocoder,
added clicking on map to create markers,
reset also clears input boxes now
2012-03-13 15:26:53 +01:00
DennisSchiefer 784f417857 changed geocoder to official OSM geocoder,
switched default map style to osm.org
2012-03-13 14:31:23 +01:00
DennisSchiefer 0bc3e098ac added GUI support for IE9 and IE10,
changed GUI legal text,
changed via-node deletion to click only,
moved default entries for input boxes to config file,
made input boxes selectable again
2012-03-13 14:15:07 +01:00
DennisSchiefer dfd3a5d554 changed round-about symbol, corrected bug with ENTER not working on
location input
2012-03-13 10:26:31 +01:00
DennisSchiefer 9dcc472c60 Merge branch 'feature/prefetching' into develop 2012-03-12 13:33:14 +01:00
DennisSchiefer c972e2cf41 Merge branch 'gui/buttons' into develop 2012-03-12 13:26:38 +01:00
DennisSchiefer de9ab83cea ignore eclipse files 2012-03-12 13:16:32 +01:00
schiefer 174e388e2d debug window added,
when including OSRM.debug, a debug window is shown
2012-03-12 11:33:39 +01:00
DennisSchiefer ee41fb45b7 added more turn instructions, changed clickability of gui 2012-03-10 17:08:25 +01:00
schiefer 93892b9806 changed buttons look 2012-03-09 17:33:06 +01:00
schiefer 749d83a69f - store prefetched images permanently
(otherwise they are not prefetched before the function terminated)
- store each type of marker icon once
2012-03-09 15:26:32 +01:00
schiefer 8b109904c8 initial import 2012-03-09 09:24:51 +01:00
313 changed files with 10195 additions and 27432 deletions
+2 -83
View File
@@ -1,83 +1,2 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
ehthumbs.db
Icon?
Thumbs.db
# build related files #
#######################
/build/
/Util/UUID.cpp
# Eclipse related files #
#########################
.setting*
.scb
.cproject
.project
# stxxl related files #
#######################
.stxxl
stxxl.log
stxxl.errlog
# compiled protobuffers #
#########################
/DataStructures/pbf-proto/*.pb.h
/DataStructures/pbf-proto/*.pb.cc
# External Libs #
#################
/lib/
/win/lib
# Visual Studio Temp + build Files #
####################################
/win/*.user
/win/*.ncb
/win/*.suo
/win/Debug/
/win/Release/
/win/bin/
/win/bin-debug/
/osrm-extract
/osrm-routed
/osrm-prepare
/osrm-cli
/nohup.out
# Sandbox folder #
###################
/sandbox/
/test/profile.lua
/.settings
/.project
View File
-39
View File
@@ -1,39 +0,0 @@
language: cpp
compiler:
- gcc
# - clang
# Make sure CMake is installed
install:
- sudo apt-get update >/dev/null
- sudo apt-get -q install build-essential git cmake pkg-config libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost-thread-dev libboost-system-dev libboost-regex-dev libboost-filesystem-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
before_script:
- sudo gem install bundler
- bundle install
- mkdir build
- cd build
- cmake .. $CMAKEOPTIONS
script: make
after_script:
- cd ..
- cucumber -p verify
branches:
only:
- master
- develop
env:
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
notifications:
irc:
channels:
- irc.oftc.net#osrm
on_success: change
on_failure: always
use_notice: true
skip_join: false
recipients:
- dennis@mapbox.com
email:
on_success: change
on_failure: always
-11
View File
@@ -1,11 +0,0 @@
The following people contributed code to the Open Source Routing Machine:
Christian Vetter
Dennis Luxen
Ruslan Krenzler
Frederik Ramm
Bharath Vissapragada
Pascal Neis
Sasa Ivetic
Emil Tin
Henning Moll
-50
View File
@@ -1,50 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BRESENHAM_H_
#define BRESENHAM_H_
#include <cmath>
#include <vector>
typedef std::pair<unsigned, unsigned> BresenhamPixel;
inline void Bresenham (int x0, int y0, const int x1, int const y1, std::vector<BresenhamPixel> &resultList) {
int dx = std::abs(x1-x0);
int dy = std::abs(y1-y0);
int sx = (x0 < x1 ? 1 : -1);
int sy = (y0 < y1 ? 1 : -1);
int err = dx - dy;
while(true) {
resultList.push_back(std::make_pair(x0,y0));
if(x0 == x1 && y0 == y1) break;
int e2 = 2* err;
if ( e2 > -dy) {
err -= dy;
x0 += sx;
}
if(e2 < dx) {
err+= dx;
y0 += sy;
}
}
}
#endif /* BRESENHAM_H_ */
-85
View File
@@ -1,85 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "CRC32.h"
CRC32::CRC32() : crc(0) {
crcFunction = detectBestCRC32C();
}
unsigned CRC32::SoftwareBasedCRC32(char *str, unsigned len, unsigned ) {
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
CRC32_Processor.process_bytes( str, len);
return CRC32_Processor.checksum();
}
unsigned CRC32::SSEBasedCRC32( char *str, unsigned len, unsigned crc) {
unsigned q=len/sizeof(unsigned),
r=len%sizeof(unsigned),
*p=(unsigned*)str/*, crc*/;
//crc=0;
while (q--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*p)
);
++p;
}
str=(char*)p;
while (r--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*str)
);
++str;
}
return crc;
}
CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
static const int SSE42_BIT = 20;
unsigned ecx = cpuid(1);
bool hasSSE42 = ecx & (1 << SSE42_BIT);
if (hasSSE42) {
SimpleLogger().Write() << "using hardware base sse computation";
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else {
SimpleLogger().Write() << "using software base sse computation";
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
}
}
unsigned CRC32::cpuid(unsigned functionInput) {
unsigned eax;
unsigned ebx;
unsigned ecx;
unsigned edx;
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
return ecx;
}
unsigned CRC32::operator()(char *str, unsigned len){
crc =((*this).*(crcFunction))(str, len, crc);
return crc;
}
-47
View File
@@ -1,47 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CRC32_H_
#define CRC32_H_
#include "../Util/SimpleLogger.h"
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream>
class CRC32 {
private:
unsigned crc;
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned crc);
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc);
unsigned cpuid(unsigned functionInput);
CRC32CFunctionPtr detectBestCRC32C();
CRC32CFunctionPtr crcFunction;
public:
CRC32();
unsigned operator()(char *str, unsigned len);
virtual ~CRC32() {};
};
#endif /* CRC32_H_ */
-130
View File
@@ -1,130 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DOUGLASPEUCKER_H_
#define DOUGLASPEUCKER_H_
#include "../DataStructures/Coordinate.h"
#include <cassert>
#include <cmath>
#include <cfloat>
#include <stack>
#include <vector>
/*This class object computes the bitvector of indicating generalized input points
* according to the (Ramer-)Douglas-Peucker algorithm.
*
* Input is vector of pairs. Each pair consists of the point information and a bit
* indicating if the points is present in the generalization.
* Note: points may also be pre-selected*/
//These thresholds are more or less heuristically chosen.
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16, 6, 3. , 3. };
template<class PointT>
class DouglasPeucker {
private:
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
//Stack to simulate the recursion
std::stack<PairOfPoints > recursionStack;
/**
* This distance computation does integer arithmetic only and is about twice as fast as
* the other distance function. It is an approximation only, but works more or less ok.
*/
template<class CoordT>
inline int fastDistance(const CoordT& point, const CoordT& segA, const CoordT& segB) const {
const int p2x = (segB.lon - segA.lat);
const int p2y = (segB.lon - segA.lat);
const int something = p2x*p2x + p2y*p2y;
int u = (something < FLT_EPSILON ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
if (u > 1)
u = 1;
else if (u < 0)
u = 0;
const int x = segA.lon + u * p2x;
const int y = segA.lat + u * p2y;
const int dx = x - point.lon;
const int dy = y - point.lat;
const int dist = (dx*dx + dy*dy);
return dist;
}
public:
void Run(std::vector<PointT> & inputVector, const unsigned zoomLevel) {
{
assert(zoomLevel < 19);
assert(1 < inputVector.size());
std::size_t leftBorderOfRange = 0;
std::size_t rightBorderOfRange = 1;
//Sweep linerarily over array and identify those ranges that need to be checked
// recursionStack.hint(inputVector.size());
do {
assert(inputVector[leftBorderOfRange].necessary);
assert(inputVector.back().necessary);
if(inputVector[rightBorderOfRange].necessary) {
recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange));
leftBorderOfRange = rightBorderOfRange;
}
++rightBorderOfRange;
} while( rightBorderOfRange < inputVector.size());
}
while(!recursionStack.empty()) {
//pop next element
const PairOfPoints pair = recursionStack.top();
recursionStack.pop();
assert(inputVector[pair.first].necessary);
assert(inputVector[pair.second].necessary);
assert(pair.second < inputVector.size());
assert(pair.first < pair.second);
int maxDistance = INT_MIN;
std::size_t indexOfFarthestElement = pair.second;
//find index idx of element with maxDistance
for(std::size_t i = pair.first+1; i < pair.second; ++i){
const double distance = std::fabs(fastDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location));
if(distance > DouglasPeuckerThresholds[zoomLevel] && distance > maxDistance) {
indexOfFarthestElement = i;
maxDistance = distance;
}
}
if (maxDistance > DouglasPeuckerThresholds[zoomLevel]) {
// mark idx as necessary
inputVector[indexOfFarthestElement].necessary = true;
if (1 < indexOfFarthestElement - pair.first) {
recursionStack.push(std::make_pair(pair.first, indexOfFarthestElement) );
}
if (1 < pair.second - indexOfFarthestElement)
recursionStack.push(std::make_pair(indexOfFarthestElement, pair.second) );
}
}
}
};
#endif /* DOUGLASPEUCKER_H_ */
-111
View File
@@ -1,111 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef ITERATORBASEDCRC32_H_
#define ITERATORBASEDCRC32_H_
#include "../Util/SimpleLogger.h"
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream>
template<class ContainerT>
class IteratorbasedCRC32 {
private:
typedef typename ContainerT::iterator ContainerT_iterator;
unsigned crc;
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
CRC32_Processor.process_bytes( str, len);
return CRC32_Processor.checksum();
}
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc){
unsigned q=len/sizeof(unsigned),
r=len%sizeof(unsigned),
*p=(unsigned*)str/*, crc*/;
//crc=0;
while (q--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*p)
);
++p;
}
str=(char*)p;
while (r--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*str)
);
++str;
}
return crc;
}
unsigned cpuid(unsigned functionInput){
unsigned eax;
unsigned ebx;
unsigned ecx;
unsigned edx;
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
return ecx;
}
CRC32CFunctionPtr detectBestCRC32C(){
static const int SSE42_BIT = 20;
unsigned ecx = cpuid(1);
bool hasSSE42 = ecx & (1 << SSE42_BIT);
if (hasSSE42) {
SimpleLogger().Write() << "using hardware based CRC32 computation";
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else {
SimpleLogger().Write() << "using software based CRC32 computation";
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
}
}
CRC32CFunctionPtr crcFunction;
public:
IteratorbasedCRC32(): crc(0) {
crcFunction = detectBestCRC32C();
}
virtual ~IteratorbasedCRC32() { }
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
unsigned crc = 0;
while(iter != end) {
char * data = reinterpret_cast<char*>(&(*iter) );
crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
++iter;
}
return crc;
}
};
#endif /* ITERATORBASEDCRC32_H_ */
-93
View File
@@ -1,93 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef OBJECTTOBASE64_H_
#define OBJECTTOBASE64_H_
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
#include <string>
#include <vector>
typedef
boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<const char *, 6, 8>
> base64_t;
typedef
boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<
std::string::const_iterator>, 8, 6
> binary_t;
template<class ObjectT>
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
const char * char_ptr_to_object = (const char *)&object;
std::vector<unsigned char> data(sizeof(object));
std::copy(
char_ptr_to_object,
char_ptr_to_object + sizeof(ObjectT),
data.begin()
);
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
while(data.size() % 3 != 0) {
++number_of_padded_chars;
data.push_back(0x00);
}
BOOST_ASSERT_MSG(
0 == data.size() % 3,
"base64 input data size is not a multiple of 3!"
);
encoded.resize(sizeof(ObjectT));
encoded.assign(
base64_t( &data[0] ),
base64_t( &data[0] + (data.size() - number_of_padded_chars) )
);
replaceAll(encoded, "+", "-");
replaceAll(encoded, "/", "_");
}
template<class ObjectT>
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
try {
std::string encoded(input);
//replace "-" with "+" and "_" with "/"
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
std::copy (
binary_t( encoded.begin() ),
binary_t( encoded.begin() + encoded.length() - 1),
(char *)&object
);
} catch(...) { }
}
#endif /* OBJECTTOBASE64_H_ */
-136
View File
@@ -1,136 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_
#include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h"
#include <string>
class PolylineCompressor {
private:
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
for(unsigned i = 0; i < numbers.size(); ++i) {
numbers[i] <<= 1;
if (numbers[i] < 0) {
numbers[i] = ~(numbers[i]);
}
}
for(unsigned i = 0; i < numbers.size(); ++i) {
encodeNumber(numbers[i], output);
}
}
inline void encodeNumber(int numberToEncode, std::string & output) const {
while (numberToEncode >= 0x20) {
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
output += (static_cast<char> (nextValue));
if(92 == nextValue)
output += (static_cast<char> (nextValue));
numberToEncode >>= 5;
}
numberToEncode += 63;
output += (static_cast<char> (numberToEncode));
if(92 == numberToEncode)
output += (static_cast<char> (numberToEncode));
}
public:
inline void printEncodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const {
std::vector<int> deltaNumbers;
output += "\"";
if(!polyline.empty()) {
FixedPointCoordinate lastCoordinate = polyline[0].location;
deltaNumbers.push_back( lastCoordinate.lat );
deltaNumbers.push_back( lastCoordinate.lon );
for(unsigned i = 1; i < polyline.size(); ++i) {
if(!polyline[i].necessary)
continue;
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
lastCoordinate = polyline[i].location;
}
encodeVectorSignedNumber(deltaNumbers, output);
}
output += "\"";
}
inline void printEncodedString(const std::vector<FixedPointCoordinate>& polyline, std::string &output) const {
std::vector<int> deltaNumbers(2*polyline.size());
output += "\"";
if(!polyline.empty()) {
deltaNumbers[0] = polyline[0].lat;
deltaNumbers[1] = polyline[0].lon;
for(unsigned i = 1; i < polyline.size(); ++i) {
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
}
encodeVectorSignedNumber(deltaNumbers, output);
}
output += "\"";
}
inline void printUnencodedString(std::vector<FixedPointCoordinate> & polyline, std::string & output) const {
output += "[";
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
convertInternalLatLonToString(polyline[i].lat, tmp);
output += "[";
output += tmp;
convertInternalLatLonToString(polyline[i].lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
inline void printUnencodedString(std::vector<SegmentInformation> & polyline, std::string & output) const {
output += "[";
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
if(!polyline[i].necessary)
continue;
convertInternalLatLonToString(polyline[i].location.lat, tmp);
output += "[";
output += tmp;
convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
};
#endif /* POLYLINECOMPRESSOR_H_ */
-419
View File
@@ -1,419 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
Strongly connected components using Tarjan's Algorithm
*/
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/integer.hpp>
#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#ifdef __APPLE__
#include <gdal.h>
#include <ogrsf_frmts.h>
#else
#include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h>
#endif
#include <cassert>
#include <stack>
#include <vector>
class TarjanSCC {
private:
struct TarjanNode {
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
unsigned index;
unsigned lowlink;
bool onStack;
};
struct TarjanEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID:31;
bool shortcut:1;
short type;
bool isAccessRestricted:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
bool reversedEdge:1;
};
struct TarjanStackFrame {
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
NodeID v;
NodeID parent;
};
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
std::vector<NodeInfo> inputNodeInfoList;
unsigned numberOfTurnRestrictions;
boost::shared_ptr<TarjanDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
RestrictionMap _restrictionMap;
struct EdgeBasedNode {
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
public:
TarjanSCC(
int nodes,
std::vector<NodeBasedEdge> & inputEdges,
std::vector<NodeID> & bn,
std::vector<NodeID> & tl,
std::vector<TurnRestriction> & irs,
std::vector<NodeInfo> & nI
) :
inputNodeInfoList(nI),
numberOfTurnRestrictions(irs.size())
{
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
restriction.fromNode, restriction.viaNode
);
unsigned index;
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
if(restrIter == _restrictionMap.end()) {
index = _restrictionBucketVector.size();
_restrictionBucketVector.resize(index+1);
_restrictionMap[restrictionSource] = index;
} else {
index = restrIter->second;
//Map already contains an is_only_*-restriction
if(_restrictionBucketVector.at(index).begin()->second)
continue;
else if(restriction.flags.isOnly){
//We are going to insert an is_only_*-restriction. There can be only one.
_restrictionBucketVector.at(index).clear();
}
}
_restrictionBucketVector.at(index).push_back(
std::make_pair(restriction.toNode, restriction.flags.isOnly)
);
}
BOOST_FOREACH(NodeID id, bn) {
_barrierNodes[id] = true;
}
BOOST_FOREACH(NodeID id, tl) {
_trafficLights[id] = true;
}
DeallocatingVector< TarjanEdge > edges;
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
TarjanEdge edge;
if(!i->isForward()) {
edge.source = i->target();
edge.target = i->source();
edge.data.backward = i->isForward();
edge.data.forward = i->isBackward();
} else {
edge.source = i->source();
edge.target = i->target();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
}
if(edge.source == edge.target)
continue;
edge.data.distance = (std::max)((int)i->weight(), 1 );
assert( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = i->isRoundabout();
edge.data.ignoreInGrid = i->ignoreInGrid();
edge.data.nameID = i->name();
edge.data.type = i->type();
edge.data.isAccessRestricted = i->isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edge.data.reversedEdge = false;
edges.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edge.data.edgeBasedNodeID = edges.size();
edge.data.reversedEdge = true;
edges.push_back( edge );
}
}
std::vector<NodeBasedEdge>().swap(inputEdges);
std::sort( edges.begin(), edges.end() );
_nodeBasedGraph = boost::make_shared<TarjanDynamicGraph>( nodes, edges );
}
void Run() {
//remove files from previous run if exist
DeleteFileIfExists("component.dbf");
DeleteFileIfExists("component.shx");
DeleteFileIfExists("component.shp");
Percent p(_nodeBasedGraph->GetNumberOfNodes());
const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver *poDriver;
OGRRegisterAll();
poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
pszDriverName );
if( poDriver == NULL )
{
printf( "%s driver not available.\n", pszDriverName );
exit( 1 );
}
OGRDataSource *poDS;
poDS = poDriver->CreateDataSource( "component.shp", NULL );
if( poDS == NULL ) {
printf( "Creation of output file failed.\n" );
exit( 1 );
}
OGRLayer *poLayer;
poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL );
if( poLayer == NULL ) {
printf( "Layer creation failed.\n" );
exit( 1 );
}
//The following is a hack to distinguish between stuff that happens before the recursive call and stuff that happens after
std::stack<std::pair<bool, TarjanStackFrame> > recursionStack; //true = stuff before, false = stuff after call
std::stack<NodeID> tarjanStack;
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
std::vector<NodeID> vectorOfComponentSizes;
std::vector<TarjanNode> tarjanNodes(_nodeBasedGraph->GetNumberOfNodes());
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
int index = 0;
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
if(UINT_MAX == componentsIndex[node]) {
recursionStack.push(std::make_pair(true, TarjanStackFrame(node,node)) );
}
while(!recursionStack.empty()) {
bool beforeRecursion = recursionStack.top().first;
TarjanStackFrame currentFrame = recursionStack.top().second;
NodeID v = currentFrame.v;
// SimpleLogger().Write() << "popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion";
recursionStack.pop();
if(beforeRecursion) {
//Mark frame to handle tail of recursion
recursionStack.push(std::make_pair(false, currentFrame));
//Mark essential information for SCC
tarjanNodes[v].index = index;
tarjanNodes[v].lowlink = index;
tarjanStack.push(v);
tarjanNodes[v].onStack = true;
++index;
// SimpleLogger().Write() << "pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink;
//Traverse outgoing edges
for(TarjanDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
TarjanDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
// SimpleLogger().Write() << "traversing edge (" << v << "," << vprime << ")";
if(UINT_MAX == tarjanNodes[vprime].index) {
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
} else {
// SimpleLogger().Write() << "Node " << vprime << " is already explored";
if(tarjanNodes[vprime].onStack) {
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
// SimpleLogger().Write() << "Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink;
tarjanNodes[v].lowlink = newLowlink;
// } else {
// SimpleLogger().Write() << "But node " << vprime << " is not on stack";
}
}
}
} else {
// SimpleLogger().Write() << "we are at the end of recursion and checking node " << v;
{ // setting lowlink in its own scope so it does not pollute namespace
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
// SimpleLogger().Write() << "parent=" << currentFrame.parent;
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
//Note the index shift by 1 compared to the recursive version
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
// SimpleLogger().Write() << "Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
}
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index;
//after recursion, lets do cycle checking
//Check if we found a cycle. This is the bottom part of the recursion
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
NodeID vprime;
do {
// SimpleLogger().Write() << "identified component " << currentComponent << ": " << tarjanStack.top();
vprime = tarjanStack.top(); tarjanStack.pop();
tarjanNodes[vprime].onStack = false;
componentsIndex[vprime] = currentComponent;
++sizeOfCurrentComponent;
} while( v != vprime);
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
if(sizeOfCurrentComponent > 1000)
SimpleLogger().Write() << "large component [" << currentComponent << "]=" << sizeOfCurrentComponent;
++currentComponent;
sizeOfCurrentComponent = 0;
}
}
}
}
SimpleLogger().Write() << "identified: " << vectorOfComponentSizes.size() << " many components, marking small components";
int singleCounter = 0;
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
if(1 == vectorOfComponentSizes[i])
++singleCounter;
}
SimpleLogger().Write() << "identified " << singleCounter << " SCCs of size 1";
uint64_t total_network_distance = 0;
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
for(TarjanDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
p.printIncrement();
for(TarjanDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
if(_nodeBasedGraph->GetEdgeData(e1).reversedEdge) {
continue;
}
TarjanDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
total_network_distance += 100*ApproximateDistance(
inputNodeInfoList[u].lat,
inputNodeInfoList[u].lon,
inputNodeInfoList[v].lat,
inputNodeInfoList[v].lon
);
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
assert(e1 != UINT_MAX);
assert(u != UINT_MAX);
assert(v != UINT_MAX);
//edges that end on bollard nodes may actually be in two distinct components
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
//INFO("(" << inputNodeInfoList[u].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[u].lon/COORDINATE_PRECISION << ") -> (" << inputNodeInfoList[v].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[v].lon/COORDINATE_PRECISION << ")");
OGRLineString lineString;
lineString.addPoint(inputNodeInfoList[u].lon/COORDINATE_PRECISION, inputNodeInfoList[u].lat/COORDINATE_PRECISION);
lineString.addPoint(inputNodeInfoList[v].lon/COORDINATE_PRECISION, inputNodeInfoList[v].lat/COORDINATE_PRECISION);
OGRFeature *poFeature;
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
poFeature->SetGeometry( &lineString );
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) {
throw OSRMException(
"Failed to create feature in shapefile."
);
}
OGRFeature::DestroyFeature( poFeature );
}
}
}
}
OGRDataSource::DestroyDataSource( poDS );
std::vector<NodeID>().swap(vectorOfComponentSizes);
std::vector<NodeID>().swap(componentsIndex);
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance/100/1000. << " km";
}
private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
if(restrictionTarget.second) {
return restrictionTarget.first;
}
}
}
return UINT_MAX;
}
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
if(w == restrictionTarget.first)
return true;
}
}
return false;
}
void DeleteFileIfExists(const std::string file_name) const {
if (boost::filesystem::exists(file_name) ) {
boost::filesystem::remove(file_name);
}
}
};
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
-160
View File
@@ -1,160 +0,0 @@
cmake_minimum_required(VERSION 2.6)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(OSRM)
include(FindPackageHandleStandardArgs)
TRY_RUN(SHARED_LIBRARY_PATH_TYPE SHARED_LIBRARY_PATH_INFO_COMPILED ${PROJECT_BINARY_DIR}/CMakeTmp ${PROJECT_SOURCE_DIR}/cmake/size.cpp OUTPUT_VARIABLE IS_64_SYSTEM)
if(IS_64_SYSTEM)
message(STATUS "System supports 64 bits.")
set( HAS64BITS 1 )
else(IS_64_SYSTEM)
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
set( HAS64BITS 0 )
endif(IS_64_SYSTEM)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
DEPENDS
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
COMMENT "Configuring UUID.cpp"
VERBATIM)
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
set(BOOST_COMPONENTS filesystem regex system thread)
file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources} )
file(GLOB PrepareGlob Contractor/*.cpp)
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
add_executable(osrm-prepare ${PrepareSources} )
add_executable(osrm-routed routed.cpp )
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB LibOSRMGlob Library/*.cpp)
file(GLOB SearchEngineSource DataStructures/SearchEngine*.cpp)
file(GLOB ServerStructureGlob Server/DataStructures/*.cpp)
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${SearchEngineSource} ${ServerStructureGlob})
add_library(OSRM SHARED ${OSRMSources})
add_library(UUID STATIC Util/UUID.cpp)
add_dependencies( UUID UUIDConfigure )
# Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
if(CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Configuring OSRM in debug mode")
endif(CMAKE_BUILD_TYPE MATCHES Debug)
if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
endif(CMAKE_BUILD_TYPE MATCHES Release)
#Configuring compilers
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
message(STATUS "OpenMP parallelization not available using clang++")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
endif()
if(APPLE)
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
message("Set Architecture to x64 on OS X")
endif()
#Check Boost
set(BOOST_MIN_VERSION "1.44.0")
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
if (NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
endif (NOT Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
IF( APPLE )
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID )
ELSE( APPLE )
target_link_libraries( OSRM ${Boost_LIBRARIES} )
ENDIF( APPLE )
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID )
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID )
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID )
find_package ( BZip2 REQUIRED )
include_directories(${BZIP_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
find_package( ZLIB REQUIRED )
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
find_package( Threads REQUIRED )
target_link_libraries (osrm-extract ${Threads_LIBRARY})
find_package( LuaJIT )
IF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES)
include_directories(${LUAJIT_INCLUDE_DIR})
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
ELSE( LUAJIT_INCLUDE_DIR )
find_package( Lua51 REQUIRED AND LUAJIT_LIBRARIES )
include_directories(${LUA_INCLUDE_DIR})
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
ENDIF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES )
find_package( LibXml2 REQUIRED )
include_directories(${LIBXML2_INCLUDE_DIR})
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
find_package( Luabind REQUIRED )
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
find_package( Protobuf REQUIRED )
include_directories(${PROTOBUF_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
find_package( STXXL REQUIRED )
include_directories(${STXXL_INCLUDE_DIR})
target_link_libraries (OSRM ${STXXL_LIBRARY})
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
find_package( OSMPBF REQUIRED )
include_directories(${OSMPBF_INCLUDE_DIR})
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
if(WITH_TOOLS)
message("-- Activating OSRM internal tools")
find_package( GDAL )
if(GDAL_FOUND)
add_executable(osrm-components Tools/componentAnalysis.cpp)
include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries(
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID
)
endif(GDAL_FOUND)
add_executable ( osrm-cli Tools/simpleclient.cpp )
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID )
endif(WITH_TOOLS)
-786
View File
@@ -1,786 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONTRACTOR_H_INCLUDED
#define CONTRACTOR_H_INCLUDED
#include "TemporaryStorage.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/XORFastHash.h"
#include "../DataStructures/XORFastHashStorage.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <cfloat>
#include <ctime>
#include <algorithm>
#include <limits>
#include <vector>
class Contractor {
private:
struct _ContractorEdgeData {
_ContractorEdgeData() :
distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {}
_ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
unsigned distance;
unsigned id;
unsigned originalEdges:28;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool originalViaNodeID:1;
} data;
struct _HeapData {
short hop;
bool target;
_HeapData() : hop(0), target(false) {}
_HeapData( short h, bool t ) : hop(h), target(t) {}
};
typedef DynamicGraph< _ContractorEdgeData > _DynamicGraph;
// typedef BinaryHeap< NodeID, NodeID, int, _HeapData, ArrayStorage<NodeID, NodeID> > _Heap;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID> > _Heap;
typedef _DynamicGraph::InputEdge _ContractorEdge;
struct _ThreadData {
_Heap heap;
std::vector< _ContractorEdge > insertedEdges;
std::vector< NodeID > neighbours;
_ThreadData( NodeID nodes ): heap( nodes ) { }
};
struct _PriorityData {
int depth;
_PriorityData() : depth(0) { }
};
struct _ContractionInformation {
int edgesDeleted;
int edgesAdded;
int originalEdgesDeleted;
int originalEdgesAdded;
_ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {}
};
struct _RemainingNodeData {
_RemainingNodeData() : id (0), isIndependent(false) {}
NodeID id:31;
bool isIndependent:1;
};
struct _NodePartitionor {
inline bool operator()(_RemainingNodeData & nodeData ) const {
return !nodeData.isIndependent;
}
};
public:
template<class ContainerT >
Contractor( int nodes, ContainerT& inputEdges) {
std::vector< _ContractorEdge > edges;
edges.reserve(inputEdges.size()*2);
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
_ContractorEdge newEdge;
while(diter!=dend) {
newEdge.source = diter->source();
newEdge.target = diter->target();
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
#ifndef NDEBUG
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
SimpleLogger().Write(logWARNING) <<
"Edge weight large -> " << newEdge.data.distance;
}
#endif
edges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = diter->isBackward();
newEdge.data.backward = diter->isForward();
edges.push_back( newEdge );
++diter;
}
//clear input vector and trim the current set of edges with the well-known swap trick
inputEdges.clear();
sort( edges.begin(), edges.end() );
NodeID edge = 0;
for ( NodeID i = 0; i < edges.size(); ) {
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
const NodeID id = edges[i].data.id;
//remove eigenloops
if ( source == target ) {
i++;
continue;
}
_ContractorEdge forwardEdge;
_ContractorEdge backwardEdge;
forwardEdge.source = backwardEdge.source = source;
forwardEdge.target = backwardEdge.target = target;
forwardEdge.data.forward = backwardEdge.data.backward = true;
forwardEdge.data.backward = backwardEdge.data.forward = false;
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
forwardEdge.data.id = backwardEdge.data.id = id;
forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
//remove parallel edges
while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
if ( edges[i].data.forward) {
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
}
if ( edges[i].data.backward) {
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
}
++i;
}
//merge edges (s,t) and (t,s) into bidirectional edge
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
if ( (int)forwardEdge.data.distance != std::numeric_limits< int >::max() ) {
forwardEdge.data.backward = true;
edges[edge++] = forwardEdge;
}
} else { //insert seperate edges
if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) {
edges[edge++] = forwardEdge;
}
if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) {
edges[edge++] = backwardEdge;
}
}
}
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
edges.resize( edge );
_graph = boost::make_shared<_DynamicGraph>( nodes, edges );
edges.clear();
std::vector<_ContractorEdge>().swap(edges);
// unsigned maxdegree = 0;
// NodeID highestNode = 0;
//
// for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
// unsigned degree = _graph->EndEdges(i) - _graph->BeginEdges(i);
// if(degree > maxdegree) {
// maxdegree = degree;
// highestNode = i;
// }
// }
//
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree;
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via;
// }
//Create temporary file
// GetTemporaryFileName(temporaryEdgeStorageFilename);
temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot();
std::cout << "contractor finished initalization" << std::endl;
}
~Contractor() {
//Delete temporary file
// remove(temporaryEdgeStorageFilename.c_str());
TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
}
void Run() {
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
Percent p (numberOfNodes);
const unsigned maxThreads = omp_get_max_threads();
std::vector < _ThreadData* > threadData;
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( numberOfNodes ) );
}
std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
NodeID numberOfContractedNodes = 0;
std::vector< _RemainingNodeData > remainingNodes( numberOfNodes );
std::vector< float > nodePriority( numberOfNodes );
std::vector< _PriorityData > nodeData( numberOfNodes );
//initialize the variables
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
remainingNodes[x].id = x;
}
std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
nodePriority[x] = _Evaluate( data, &nodeData[x], x );
}
}
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
bool flushedContractor = false;
while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
//Delete old heap data to free memory that we need for the coming operations
BOOST_FOREACH(_ThreadData * data, threadData)
delete data;
threadData.clear();
//Create new priority array
std::vector<float> newNodePriority(remainingNodes.size());
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
std::vector<NodeID> newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX);
//build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
//create renumbering maps in both directions
oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id;
newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID;
newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].id];
remainingNodes[newNodeID].id = newNodeID;
}
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//Write dummy number of edges to temporary file
// std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
unsigned numberOfTemporaryEdges = 0;
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
//walk over all nodes
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
const NodeID start = i;
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
const NodeID target = _graph->GetTarget(currentEdge);
if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
//Save edges of this node w/o renumbering.
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID));
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData));
++numberOfTemporaryEdges;
}else {
//node is not yet contracted.
//add (renumbered) outgoing edges to new DynamicGraph.
_ContractorEdge newEdge;
newEdge.source = newNodeIDFromOldNodeIDMap[start];
newEdge.target = newNodeIDFromOldNodeIDMap[target];
newEdge.data = data;
newEdge.data.originalViaNodeID = true;
BOOST_ASSERT_MSG(
UINT_MAX != newNodeIDFromOldNodeIDMap[start],
"new start id not resolveable"
);
BOOST_ASSERT_MSG(
UINT_MAX != newNodeIDFromOldNodeIDMap[target],
"new target id not resolveable"
);
newSetOfEdges.push_back(newEdge);
}
}
}
//Note the number of temporarily stored edges
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
//Delete map from old NodeIDs to new ones.
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
//Replace old priorities array by new one
nodePriority.swap(newNodePriority);
//Delete old nodePriority vector
std::vector<float>().swap(newNodePriority);
//old Graph is removed
_graph.reset();
//create new graph
std::sort(newSetOfEdges.begin(), newSetOfEdges.end());
_graph = boost::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges);
newSetOfEdges.clear();
flushedContractor = true;
//INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
//reinitialize heaps and ThreadData objects with appropriate size
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( _graph->GetNumberOfNodes() ) );
}
}
const int last = ( int ) remainingNodes.size();
#pragma omp parallel
{
//determine independent node set
_ThreadData* const data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided )
for ( int i = 0; i < last; ++i ) {
const NodeID node = remainingNodes[i].id;
remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node );
}
}
_NodePartitionor functor;
const std::vector < _RemainingNodeData >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), functor );
const int firstIndependent = first - remainingNodes.begin();
//contract independent nodes
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].id;
_Contract< false > ( data, x );
//nodePriority[x] = -1;
}
std::sort( data->insertedEdges.begin(), data->insertedEdges.end() );
}
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].id;
_DeleteIncomingEdges( data, x );
}
}
//insert new edges
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
_ThreadData& data = *threadData[threadNum];
BOOST_FOREACH(const _ContractorEdge& edge, data.insertedEdges) {
_DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target);
if(currentEdgeID < _graph->EndEdges(edge.source) ) {
_DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID);
if( currentEdgeData.shortcut
&& edge.data.forward == currentEdgeData.forward
&& edge.data.backward == currentEdgeData.backward ) {
currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
continue;
}
}
_graph->InsertEdge( edge.source, edge.target, edge.data );
}
data.insertedEdges.clear();
}
//update priorities
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].id;
_UpdateNeighbours( nodePriority, nodeData, data, x );
}
}
//remove contracted nodes from the pool
numberOfContractedNodes += last - firstIndependent;
remainingNodes.resize( firstIndependent );
std::vector< _RemainingNodeData>( remainingNodes ).swap( remainingNodes );
// unsigned maxdegree = 0;
// unsigned avgdegree = 0;
// unsigned mindegree = UINT_MAX;
// unsigned quaddegree = 0;
//
// for(unsigned i = 0; i < remainingNodes.size(); ++i) {
// unsigned degree = _graph->EndEdges(remainingNodes[i].first) - _graph->BeginEdges(remainingNodes[i].first);
// if(degree > maxdegree)
// maxdegree = degree;
// if(degree < mindegree)
// mindegree = degree;
//
// avgdegree += degree;
// quaddegree += (degree*degree);
// }
//
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
//
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree;
p.printStatus(numberOfContractedNodes);
}
BOOST_FOREACH(_ThreadData * data, threadData) {
delete data;
}
threadData.clear();
}
template< class Edge >
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
Percent p (_graph->GetNumberOfNodes());
SimpleLogger().Write() << "Getting edges of minimized graph";
NodeID numberOfNodes = _graph->GetNumberOfNodes();
if(_graph->GetNumberOfNodes()) {
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
p.printStatus(node);
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
const NodeID target = _graph->GetTarget( edge );
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
Edge newEdge;
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
} else {
newEdge.source = node;
newEdge.target = target;
}
BOOST_ASSERT_MSG(
UINT_MAX != newEdge.source,
"Source id invalid"
);
BOOST_ASSERT_MSG(
UINT_MAX != newEdge.target,
"Target id invalid"
);
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
} else {
newEdge.data.id = data.id;
}
BOOST_ASSERT_MSG(
newEdge.data.id != INT_MAX, //2^31
"edge id invalid"
);
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
}
}
_graph.reset();
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//Also get the edges from temporary storage
unsigned numberOfTemporaryEdges = 0;
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
//loads edges of graph before renumbering, no need for further numbering action.
NodeID start;
NodeID target;
//edges.reserve(edges.size()+numberOfTemporaryEdges);
_DynamicGraph::EdgeData data;
for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID));
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData));
Edge newEdge;
newEdge.source = start;
newEdge.target = target;
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
newEdge.data.id = data.id;
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
tempStorage.deallocateSlot(temporaryStorageSlotID);
}
private:
inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){
_Heap& heap = data->heap;
int nodes = 0;
unsigned targetsFound = 0;
while ( heap.Size() > 0 ) {
const NodeID node = heap.DeleteMin();
const int distance = heap.GetKey( node );
const short currentHop = heap.GetData( node ).hop+1;
if ( ++nodes > maxNodes )
return;
//Destination settled?
if ( distance > maxDistance )
return;
if ( heap.GetData( node ).target ) {
++targetsFound;
if ( targetsFound >= numTargets ) {
return;
}
}
//iterate over all edges of node
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
if ( !data.forward ){
continue;
}
const NodeID to = _graph->GetTarget( edge );
if(middleNode == to) {
continue;
}
const int toDistance = distance + data.distance;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !heap.WasInserted( to ) ) {
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
}
//Found a shorter Path -> Update distance
else if ( toDistance < heap.GetKey( to ) ) {
heap.DecreaseKey( to, toDistance );
heap.GetData( to ).hop = currentHop;
}
}
}
}
inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
_ContractionInformation stats;
//perform simulated contraction
_Contract< true> ( data, node, &stats );
// Result will contain the priority
float result;
if ( 0 == (stats.edgesDeleted*stats.originalEdgesDeleted) )
result = 1 * nodeData->depth;
else
result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
assert( result >= 0 );
return result;
}
template< bool Simulate >
inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
_Heap& heap = data->heap;
int insertedEdgesSize = data->insertedEdges.size();
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
const _ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
const NodeID source = _graph->GetTarget( inEdge );
if ( Simulate ) {
assert( stats != NULL );
++stats->edgesDeleted;
stats->originalEdgesDeleted += inData.originalEdges;
}
if ( !inData.backward )
continue;
heap.Clear();
heap.Insert( source, 0, _HeapData() );
int maxDistance = 0;
unsigned numTargets = 0;
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) {
continue;
}
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
maxDistance = std::max( maxDistance, pathDistance );
if ( !heap.WasInserted( target ) ) {
heap.Insert( target, INT_MAX, _HeapData( 0, true ) );
++numTargets;
}
}
if( Simulate ) {
_Dijkstra( maxDistance, numTargets, 1000, data, node );
} else {
_Dijkstra( maxDistance, numTargets, 2000, data, node );
}
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) {
continue;
}
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
const int distance = heap.GetKey( target );
if ( pathDistance < distance ) {
if ( Simulate ) {
assert( stats != NULL );
stats->edgesAdded+=2;
stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges );
} else {
_ContractorEdge newEdge;
newEdge.source = source;
newEdge.target = target;
newEdge.data = _ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
insertedEdges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = false;
newEdge.data.backward = true;
insertedEdges.push_back( newEdge );
}
}
}
}
if ( !Simulate ) {
for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i ) {
bool found = false;
for ( int other = i + 1 ; other < iend ; ++other ) {
if ( insertedEdges[other].source != insertedEdges[i].source )
continue;
if ( insertedEdges[other].target != insertedEdges[i].target )
continue;
if ( insertedEdges[other].data.distance != insertedEdges[i].data.distance )
continue;
if ( insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut )
continue;
insertedEdges[other].data.forward |= insertedEdges[i].data.forward;
insertedEdges[other].data.backward |= insertedEdges[i].data.backward;
found = true;
break;
}
if ( !found ) {
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
}
}
insertedEdges.resize( insertedEdgesSize );
}
return true;
}
inline void _DeleteIncomingEdges( _ThreadData* data, const NodeID node ) {
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
//find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID u = _graph->GetTarget( e );
if ( u != node )
neighbours.push_back( u );
}
//eliminate duplicate entries ( forward + backward edges )
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
_graph->DeleteEdgesTo( neighbours[i], node );
}
}
inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, const NodeID node) {
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
//find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ) ; e < endEdges ; ++e ) {
const NodeID u = _graph->GetTarget( e );
if ( u == node )
continue;
neighbours.push_back( u );
nodeData[u].depth = (std::max)(nodeData[node].depth + 1, nodeData[u].depth );
}
//eliminate duplicate entries ( forward + backward edges )
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
BOOST_FOREACH(const NodeID u, neighbours) {
priorities[u] = _Evaluate( data, &( nodeData )[u], u );
}
return true;
}
inline bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) const {
const double priority = priorities[node];
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID target = _graph->GetTarget( e );
if(node==target)
continue;
const double targetPriority = priorities[target];
assert( targetPriority >= 0 );
//found a neighbour with lower priority?
if ( priority > targetPriority )
return false;
//tie breaking
if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
return false;
}
neighbours.push_back( target );
}
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
//examine all neighbours that are at most 2 hops away
BOOST_FOREACH(const NodeID u, neighbours) {
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
const NodeID target = _graph->GetTarget( e );
if(node==target)
continue;
const double targetPriority = priorities[target];
assert( targetPriority >= 0 );
//found a neighbour with lower priority?
if ( priority > targetPriority)
return false;
//tie breaking
if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
return false;
}
}
}
return true;
}
/**
* This bias function takes up 22 assembly instructions in total on X86
*/
inline bool bias(const NodeID a, const NodeID b) const {
unsigned short hasha = fastHash(a);
unsigned short hashb = fastHash(b);
//The compiler optimizes that to conditional register flags but without branching statements!
if(hasha != hashb)
return hasha < hashb;
return a < b;
}
boost::shared_ptr<_DynamicGraph> _graph;
std::vector<_DynamicGraph::InputEdge> contractedEdges;
unsigned temporaryStorageSlotID;
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
XORFastHash fastHash;
};
#endif // CONTRACTOR_H_INCLUDED
-561
View File
@@ -1,561 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "EdgeBasedGraphFactory.h"
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
int number_of_nodes,
std::vector<ImportEdge> & input_edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties speed_profile
) : speed_profile(speed_profile),
m_turn_restrictions_count(0),
m_node_info_list(m_node_info_list)
{
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
std::pair<NodeID, NodeID> restriction_source =
std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
RestrictionMap::iterator restriction_iter = m_restriction_map.find(restriction_source);
if(restriction_iter == m_restriction_map.end()) {
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index+1);
m_restriction_map[restriction_source] = index;
} else {
index = restriction_iter->second;
//Map already contains an is_only_*-restriction
if(m_restriction_bucket_list.at(index).begin()->second) {
continue;
} else if(restriction.flags.isOnly) {
//We are going to insert an is_only_*-restriction. There can be only one.
m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
}
}
++m_turn_restrictions_count;
m_restriction_bucket_list.at(index).push_back(
std::make_pair( restriction.toNode, restriction.flags.isOnly)
);
}
m_barrier_nodes.insert(
barrier_node_list.begin(),
barrier_node_list.end()
);
m_traffic_lights.insert(
traffic_light_node_list.begin(),
traffic_light_node_list.end()
);
DeallocatingVector< NodeBasedEdge > edges_list;
NodeBasedEdge edge;
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
if(!import_edge.isForward()) {
edge.source = import_edge.target();
edge.target = import_edge.source();
edge.data.backward = import_edge.isForward();
edge.data.forward = import_edge.isBackward();
} else {
edge.source = import_edge.source();
edge.target = import_edge.target();
edge.data.forward = import_edge.isForward();
edge.data.backward = import_edge.isBackward();
}
if(edge.source == edge.target) {
continue;
}
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
assert( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = import_edge.isRoundabout();
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
edge.data.nameID = import_edge.name();
edge.data.type = import_edge.type();
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
edge.data.edgeBasedNodeID = edges_list.size();
edge.data.contraFlow = import_edge.isContraFlow();
edges_list.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = import_edge.isBackward();
edge.data.backward = import_edge.isForward();
edge.data.edgeBasedNodeID = edges_list.size();
edges_list.push_back( edge );
}
}
std::vector<ImportEdge>().swap(input_edge_list);
std::sort( edges_list.begin(), edges_list.end() );
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
number_of_nodes, edges_list
);
}
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
DeallocatingVector< EdgeBasedEdge >& output_edge_list
) {
BOOST_ASSERT_MSG(
0 == output_edge_list.size(),
"Vector is not empty"
);
m_edge_based_edge_list.swap(output_edge_list);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
#ifndef NDEBUG
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
}
#endif
nodes.swap(m_edge_based_node_list);
}
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const {
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end()) {
const unsigned index = restriction_iter->second;
BOOST_FOREACH(
const RestrictionSource & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(restriction_target.second) {
return restriction_target.first;
}
}
}
return UINT_MAX;
}
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end()) {
const unsigned index = restriction_iter->second;
BOOST_FOREACH(
const RestrictionTarget & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(w == restriction_target.first) {
return true;
}
}
}
return false;
}
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
EdgeIterator e1,
NodeIterator u,
NodeIterator v,
bool belongsToTinyComponent) {
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
EdgeBasedNode currentNode;
currentNode.nameID = data.nameID;
currentNode.lat1 = m_node_info_list[u].lat;
currentNode.lon1 = m_node_info_list[u].lon;
currentNode.lat2 = m_node_info_list[v].lat;
currentNode.lon2 = m_node_info_list[v].lon;
currentNode.belongsToTinyComponent = belongsToTinyComponent;
currentNode.id = data.edgeBasedNodeID;
currentNode.ignoreInGrid = data.ignoreInGrid;
currentNode.weight = data.distance;
m_edge_based_node_list.push_back(currentNode);
}
void EdgeBasedGraphFactory::Run(
const char * original_edge_data_filename,
lua_State *lua_state
) {
SimpleLogger().Write() << "Identifying components of the road network";
Percent p(m_node_based_graph->GetNumberOfNodes());
unsigned skipped_turns_counter = 0;
unsigned node_based_edge_counter = 0;
unsigned original_edges_counter = 0;
std::ofstream edge_data_file(
original_edge_data_filename,
std::ios::binary
);
//writes a dummy value that is updated later
edge_data_file.write(
(char*)&original_edges_counter,
sizeof(unsigned)
);
unsigned current_component = 0, current_component_size = 0;
//Run a BFS on the undirected graph and identify small components
std::queue<std::pair<NodeID, NodeID> > bfs_queue;
std::vector<unsigned> component_index_list(
m_node_based_graph->GetNumberOfNodes(),
UINT_MAX
);
std::vector<NodeID> component_size_list;
//put unexplorered node with parent pointer into queue
for(
NodeID node = 0,
last_node = m_node_based_graph->GetNumberOfNodes();
node < last_node;
++node
) {
if(UINT_MAX == component_index_list[node]) {
bfs_queue.push(std::make_pair(node, node));
//mark node as read
component_index_list[node] = current_component;
p.printIncrement();
while(!bfs_queue.empty()) {
//fetch element from BFS queue
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
bfs_queue.pop();
// SimpleLogger().Write() << "sizeof queue: " << bfs_queue.size() <<
// ", current_component_sizes: " << current_component_size <<
//", settled nodes: " << settledNodes++ << ", max: " << endNodes;
const NodeID v = current_queue_item.first; //current node
const NodeID u = current_queue_item.second; //parent
//increment size counter of current component
++current_component_size;
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
if(!is_barrier_node) {
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
//relaxieren edge outgoing edge like below where edge-expanded graph
for(
EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
e2 < m_node_based_graph->EndEdges(v);
++e2
) {
NodeIterator w = m_node_based_graph->GetTarget(e2);
if(
to_node_of_only_restriction != UINT_MAX &&
w != to_node_of_only_restriction
) {
//We are at an only_-restriction but not at the right turn.
continue;
}
if( u != w ) {
//only add an edge if turn is not a U-turn except
//when it is at the end of a dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) ) {
//only add an edge if turn is not prohibited
if(UINT_MAX == component_index_list[w]) {
//insert next (node, parent) only if w has
//not yet been explored
//mark node as read
component_index_list[w] = current_component;
bfs_queue.push(std::make_pair(w,v));
p.printIncrement();
}
}
}
}
}
}
//push size into vector
component_size_list.push_back(current_component_size);
//reset counters;
current_component_size = 0;
++current_component;
}
}
SimpleLogger().Write() <<
"identified: " << component_size_list.size() << " many components";
p.reinit(m_node_based_graph->GetNumberOfNodes());
//loop over all edges and generate new set of nodes.
for(
NodeIterator u = 0,
number_of_nodes = m_node_based_graph->GetNumberOfNodes();
u < number_of_nodes;
++u
) {
for(
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
last_edge = m_node_based_graph->EndEdges(u);
e1 < last_edge;
++e1
) {
NodeIterator v = m_node_based_graph->GetTarget(e1);
if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) {
BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid");
BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid");
BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid");
//Note: edges that end on barrier nodes or on a turn restriction
//may actually be in two distinct components. We choose the smallest
const unsigned size_of_component = std::min(
component_size_list[component_index_list[u]],
component_size_list[component_index_list[v]]
);
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
}
}
}
std::vector<NodeID>().swap(component_size_list);
BOOST_ASSERT_MSG(
0 == component_size_list.capacity(),
"component size vector not deallocated"
);
std::vector<NodeID>().swap(component_index_list);
BOOST_ASSERT_MSG(
0 == component_index_list.capacity(),
"component index vector not deallocated"
);
std::vector<OriginalEdgeData> original_edge_data_vector;
original_edge_data_vector.reserve(10000);
//Loop over all turns and generate new set of edges.
//Three nested loop look super-linear, but we are dealing with a (kind of)
//linear number of turns only.
for(
NodeIterator u = 0,
last_node = m_node_based_graph->GetNumberOfNodes();
u < last_node;
++u
) {
for(
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
last_edge_u = m_node_based_graph->EndEdges(u);
e1 < last_edge_u;
++e1
) {
++node_based_edge_counter;
NodeIterator v = m_node_based_graph->GetTarget(e1);
bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
for(
EdgeIterator e2 = m_node_based_graph->BeginEdges(v),
last_edge_v = m_node_based_graph->EndEdges(v);
e2 < last_edge_v;
++e2
) {
const NodeIterator w = m_node_based_graph->GetTarget(e2);
if(
to_node_of_only_restriction != UINT_MAX &&
w != to_node_of_only_restriction
) {
//We are at an only_-restriction but not at the right turn.
++skipped_turns_counter;
continue;
}
if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) {
continue;
}
if( !is_barrier_node ) {
//only add an edge if turn is not a U-turn except when it is
//at the end of a dead-end street
if (
!CheckIfTurnIsRestricted(u, v, w) ||
(to_node_of_only_restriction != UINT_MAX && w == to_node_of_only_restriction)
) { //only add an edge if turn is not prohibited
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
assert(edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
assert(edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
if(!edge_data1.forward || !edge_data2.forward) {
continue;
}
unsigned distance = edge_data1.distance;
if(m_traffic_lights.find(v) != m_traffic_lights.end()) {
distance += speed_profile.trafficSignalPenalty;
}
const unsigned penalty =
GetTurnPenalty(u, v, w, lua_state);
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
if(turnInstruction == TurnInstructions.UTurn){
distance += speed_profile.uTurnPenalty;
}
distance += penalty;
assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
original_edge_data_vector.push_back(
OriginalEdgeData(
v,
edge_data2.nameID,
turnInstruction
)
);
++original_edges_counter;
if(original_edge_data_vector.size() > 100000) {
edge_data_file.write(
(char*)&(original_edge_data_vector[0]),
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
);
original_edge_data_vector.clear();
}
m_edge_based_edge_list.push_back(
EdgeBasedEdge(
edge_data1.edgeBasedNodeID,
edge_data2.edgeBasedNodeID,
m_edge_based_edge_list.size(),
distance,
true,
false
)
);
} else {
++skipped_turns_counter;
}
}
}
}
p.printIncrement();
}
edge_data_file.write(
(char*)&(original_edge_data_vector[0]),
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
);
edge_data_file.seekp(std::ios::beg);
edge_data_file.write(
(char*)&original_edges_counter,
sizeof(unsigned)
);
edge_data_file.close();
SimpleLogger().Write() <<
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
SimpleLogger().Write() <<
"Node-based graph contains " << node_based_edge_counter << " edges";
SimpleLogger().Write() <<
"Edge-expanded graph ...";
SimpleLogger().Write() <<
" contains " << m_edge_based_edge_list.size() << " edges";
SimpleLogger().Write() <<
" skips " << skipped_turns_counter << " turns, "
"defined by " << m_turn_restrictions_count << " restrictions";
}
int EdgeBasedGraphFactory::GetTurnPenalty(
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *lua_state
) const {
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
m_node_info_list[u],
m_node_info_list[v],
m_node_info_list[w]
);
if( speed_profile.has_turn_penalty_function ) {
try {
//call lua profile to compute turn penalty
return luabind::call_function<int>(
lua_state,
"turn_function",
180.-angle
);
} catch (const luabind::error &er) {
SimpleLogger().Write(logWARNING) << er.what();
}
}
return 0;
}
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
const NodeID u,
const NodeID v,
const NodeID w
) const {
if(u == w) {
return TurnInstructions.UTurn;
}
EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
if(!data1.contraFlow && data2.contraFlow) {
return TurnInstructions.EnterAgainstAllowedDirection;
}
if(data1.contraFlow && !data2.contraFlow) {
return TurnInstructions.LeaveAgainstAllowedDirection;
}
//roundabouts need to be handled explicitely
if(data1.roundabout && data2.roundabout) {
//Is a turn possible? If yes, we stay on the roundabout!
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
//No turn possible.
return TurnInstructions.NoTurn;
}
return TurnInstructions.StayOnRoundAbout;
}
//Does turn start or end on roundabout?
if(data1.roundabout || data2.roundabout) {
//We are entering the roundabout
if( (!data1.roundabout) && data2.roundabout) {
return TurnInstructions.EnterRoundAbout;
}
//We are leaving the roundabout
if(data1.roundabout && (!data2.roundabout) ) {
return TurnInstructions.LeaveRoundAbout;
}
}
//If street names stay the same and if we are certain that it is not a
//a segment of a roundabout, we skip it.
if( data1.nameID == data2.nameID ) {
//TODO: Here we should also do a small graph exploration to check for
// more complex situations
if( 0 != data1.nameID ) {
return TurnInstructions.NoTurn;
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
return TurnInstructions.NoTurn;
}
}
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
m_node_info_list[u],
m_node_info_list[v],
m_node_info_list[w]
);
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
}
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
return m_node_based_graph->GetNumberOfEdges();
}
-203
View File
@@ -1,203 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
// This class constructs the edge-expanded routing graph
#ifndef EDGEBASEDGRAPHFACTORY_H_
#define EDGEBASEDGRAPHFACTORY_H_
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../Extractor/ExtractorStructs.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/LuaUtil.h"
#include "../Util/SimpleLogger.h"
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <algorithm>
#include <fstream>
#include <queue>
#include <vector>
class EdgeBasedGraphFactory : boost::noncopyable {
public:
struct EdgeBasedNode {
EdgeBasedNode() :
id(INT_MAX),
lat1(INT_MAX),
lat2(INT_MAX),
lon1(INT_MAX),
lon2(INT_MAX >> 1),
belongsToTinyComponent(false),
nameID(UINT_MAX),
weight(UINT_MAX >> 1),
ignoreInGrid(false)
{ }
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
return centroid;
}
inline bool isIgnored() const {
return ignoreInGrid;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),
uTurnPenalty(0),
has_turn_penalty_function(false)
{ }
int trafficSignalPenalty;
int uTurnPenalty;
bool has_turn_penalty_function;
} speed_profile;
explicit EdgeBasedGraphFactory(
int number_of_nodes,
std::vector<ImportEdge> & input_edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties speed_profile
);
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
TurnInstruction AnalyzeTurn(
const NodeID u,
const NodeID v,
const NodeID w
) const;
int GetTurnPenalty(
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *myLuaState
) const;
unsigned GetNumberOfNodes() const;
private:
struct NodeBasedEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
short type;
bool isAccessRestricted:1;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
bool contraFlow:1;
};
struct _EdgeBasedEdgeData {
int distance;
unsigned via;
unsigned nameID;
bool forward;
bool backward;
TurnInstruction turnInstruction;
};
unsigned m_turn_restrictions_count;
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
std::vector<NodeInfo> m_node_info_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_nodes;
boost::unordered_set<NodeID> m_traffic_lights;
RestrictionMap m_restriction_map;
NodeID CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const;
bool CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const;
void InsertEdgeBasedNode(
NodeBasedDynamicGraph::EdgeIterator e1,
NodeBasedDynamicGraph::NodeIterator u,
NodeBasedDynamicGraph::NodeIterator v,
bool belongsToTinyComponent);
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
-133
View File
@@ -1,133 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() {
tempDirectory = boost::filesystem::temp_directory_path();
}
TemporaryStorage & TemporaryStorage::GetInstance(){
static TemporaryStorage runningInstance;
return runningInstance;
}
TemporaryStorage::~TemporaryStorage() {
removeAll();
}
void TemporaryStorage::removeAll() {
boost::mutex::scoped_lock lock(mutex);
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
deallocateSlot(slot_id);
}
vectorOfStreamDatas.clear();
}
int TemporaryStorage::allocateSlot() {
boost::mutex::scoped_lock lock(mutex);
try {
vectorOfStreamDatas.push_back(StreamData());
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
return vectorOfStreamDatas.size() - 1;
}
void TemporaryStorage::deallocateSlot(int slotID) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
return;
}
if(data.streamToTemporaryFile->is_open()) {
data.streamToTemporaryFile->close();
}
boost::filesystem::remove(data.pathToTemporaryFile);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG(
data.writeMode,
"Writing after first read is not allowed"
);
data.streamToTemporaryFile->write(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(data.writeMode) {
data.writeMode = false;
data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
}
data.streamToTemporaryFile->read(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
boost::filesystem::space_info tempSpaceInfo;
try {
tempSpaceInfo = boost::filesystem::space(tempDirectory);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
return tempSpaceInfo.available;
}
boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
boost::filesystem::fstream::pos_type position;
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.streamToTemporaryFile->tellp();
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
return position;
}
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
removeAll();
}
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
data.streamToTemporaryFile->seekg(position);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
-118
View File
@@ -1,118 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TEMPORARYSTORAGE_H_
#define TEMPORARYSTORAGE_H_
#include <vector>
#include <fstream>
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
//This is one big workaround for latest boost renaming woes.
#if BOOST_FILESYSTEM_VERSION < 3
#warning Boost Installation with Filesystem3 missing, activating workaround
#include <cstdio>
namespace boost {
namespace filesystem {
inline path temp_directory_path() {
char * buffer;
buffer = tmpnam (NULL);
return path(buffer);
}
inline path unique_path(const path&) {
return temp_directory_path();
}
}
}
#endif
#ifndef BOOST_FILESYSTEM_VERSION
#define BOOST_FILESYSTEM_VERSION 3
#endif
/**
* This class implements a singleton file storage for temporary data.
* temporary slots can be accessed by other objects through an int
* On deallocation every slot gets deallocated
*
* Access is sequential, which means, that there is no random access
* -> Data is written in first phase and reread in second.
*/
static boost::filesystem::path tempDirectory;
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage {
public:
static TemporaryStorage & GetInstance();
virtual ~TemporaryStorage();
int allocateSlot();
void deallocateSlot(int slotID);
void writeToSlot(int slotID, char * pointer, std::streamsize size);
void readFromSlot(int slotID, char * pointer, std::streamsize size);
//returns the number of free bytes
unsigned getFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type tell(int slotID);
void seek(int slotID, boost::filesystem::fstream::pos_type);
void removeAll();
private:
TemporaryStorage();
TemporaryStorage(TemporaryStorage const &){};
TemporaryStorage& operator=(TemporaryStorage const &) {
return *this;
}
void abort(boost::filesystem::filesystem_error& e);
struct StreamData {
bool writeMode;
boost::filesystem::path pathToTemporaryFile;
boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile;
boost::shared_ptr<boost::mutex> readWriteMutex;
StreamData() :
writeMode(true),
pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(new boost::mutex)
{
if(streamToTemporaryFile->fail()) {
throw OSRMException("temporary file could not be created");
}
}
};
//vector of file streams that is used to store temporary data
std::vector<StreamData> vectorOfStreamDatas;
boost::mutex mutex;
};
#endif /* TEMPORARYSTORAGE_H_ */
-269
View File
@@ -1,269 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BINARYHEAP_H_INCLUDED
#define BINARYHEAP_H_INCLUDED
//Not compatible with non contiguous node ids
#include <boost/unordered_map.hpp>
#include <cassert>
#include <algorithm>
#include <limits>
#include <map>
#include <vector>
template< typename NodeID, typename Key >
class ArrayStorage {
public:
ArrayStorage( size_t size ) : positions( new Key[size] ) {
memset(positions, 0, size*sizeof(Key));
}
~ArrayStorage() {
delete[] positions;
}
Key &operator[]( NodeID node ) {
return positions[node];
}
void Clear() {}
private:
Key* positions;
};
template< typename NodeID, typename Key >
class MapStorage {
public:
MapStorage( size_t ) {}
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
std::map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class UnorderedMapStorage {
public:
UnorderedMapStorage( size_t ) {
//hash table gets 1000 Buckets
nodes.rehash(1000);
}
Key &operator[]( const NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
boost::unordered_map< NodeID, Key > nodes;
};
template<typename NodeID = unsigned>
struct _SimpleHeapData {
NodeID parent;
_SimpleHeapData( NodeID p ) : parent(p) { }
};
template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID> >
class BinaryHeap {
private:
BinaryHeap( const BinaryHeap& right );
void operator=( const BinaryHeap& right );
public:
typedef Weight WeightType;
typedef Data DataType;
BinaryHeap( size_t maxID )
: nodeIndex( maxID ) {
Clear();
}
void Clear() {
heap.resize( 1 );
insertedNodes.clear();
heap[0].weight = std::numeric_limits< Weight >::min();
nodeIndex.Clear();
}
Key Size() const {
return static_cast<Key>( heap.size() - 1 );
}
void Insert( NodeID node, Weight weight, const Data &data ) {
HeapElement element;
element.index = static_cast<NodeID>(insertedNodes.size());
element.weight = weight;
const Key key = static_cast<Key>(heap.size());
heap.push_back( element );
insertedNodes.push_back( HeapNode( node, key, weight, data ) );
nodeIndex[node] = element.index;
Upheap( key );
CheckHeap();
}
Data& GetData( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].data;
}
Weight& GetKey( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].weight;
}
bool WasRemoved( const NodeID node ) {
assert( WasInserted( node ) );
const Key index = nodeIndex[node];
return insertedNodes[index].key == 0;
}
bool WasInserted( const NodeID node ) {
const Key index = nodeIndex[node];
if ( index >= static_cast<Key> (insertedNodes.size()) )
return false;
return insertedNodes[index].node == node;
}
NodeID Min() const {
assert( heap.size() > 1 );
return insertedNodes[heap[1].index].node;
}
NodeID DeleteMin() {
assert( heap.size() > 1 );
const Key removedIndex = heap[1].index;
heap[1] = heap[heap.size()-1];
heap.pop_back();
if ( heap.size() > 1 )
Downheap( 1 );
insertedNodes[removedIndex].key = 0;
CheckHeap();
return insertedNodes[removedIndex].node;
}
void DeleteAll() {
for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i )
insertedNodes[i->index].key = 0;
heap.resize( 1 );
heap[0].weight = (std::numeric_limits< Weight >::min)();
}
void DecreaseKey( NodeID node, Weight weight ) {
assert( UINT_MAX != node );
const Key & index = nodeIndex[node];
Key & key = insertedNodes[index].key;
assert ( key >= 0 );
insertedNodes[index].weight = weight;
heap[key].weight = weight;
Upheap( key );
CheckHeap();
}
private:
class HeapNode {
public:
HeapNode() {
}
HeapNode( NodeID n, Key k, Weight w, Data d )
: node( n ), key( k ), weight( w ), data( d ) {
}
NodeID node;
Key key;
Weight weight;
Data data;
};
struct HeapElement {
Key index;
Weight weight;
};
std::vector< HeapNode > insertedNodes;
std::vector< HeapElement > heap;
IndexStorage nodeIndex;
void Downheap( Key key ) {
const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key << 1;
while ( nextKey < static_cast<Key>( heap.size() ) ) {
const Key nextKeyOther = nextKey + 1;
if ( ( nextKeyOther < static_cast<Key> ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
nextKey = nextKeyOther;
if ( weight <= heap[nextKey].weight )
break;
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
nextKey <<= 1;
}
heap[key].index = droppingIndex;
heap[key].weight = weight;
insertedNodes[droppingIndex].key = key;
}
void Upheap( Key key ) {
const Key risingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key >> 1;
while ( heap[nextKey].weight > weight ) {
assert( nextKey != 0 );
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
nextKey >>= 1;
}
heap[key].index = risingIndex;
heap[key].weight = weight;
insertedNodes[risingIndex].key = key;
}
void CheckHeap() {
#ifndef NDEBUG
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
assert( heap[i].weight >= heap[i >> 1].weight );
}
#endif
}
};
#endif //#ifndef BINARYHEAP_H_INCLUDED
-83
View File
@@ -1,83 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONCURRENTQUEUE_H_INCLUDED
#define CONCURRENTQUEUE_H_INCLUDED
#include <boost/bind.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include "../typedefs.h"
template<typename Data>
class ConcurrentQueue {
typedef typename boost::circular_buffer<Data>::size_type size_t;
public:
ConcurrentQueue(const size_t max_size) : internal_queue(max_size) { }
inline void push(Data const& data) {
boost::mutex::scoped_lock lock(m_mutex);
m_not_full.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_full, this));
internal_queue.push_back(data);
lock.unlock();
m_not_empty.notify_one();
}
inline bool empty() const {
return internal_queue.empty();
}
inline void wait_and_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(m_mutex);
m_not_empty.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_empty, this));
popped_value=internal_queue.front();
internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one();
}
inline bool try_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(m_mutex);
if(internal_queue.empty()) {
return false;
}
popped_value=internal_queue.front();
internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one();
return true;
}
private:
boost::circular_buffer<Data> internal_queue;
boost::mutex m_mutex;
boost::condition m_not_empty;
boost::condition m_not_full;
inline bool is_not_empty() const { return internal_queue.size() > 0; }
inline bool is_not_full() const { return internal_queue.size() < internal_queue.capacity(); }
};
#endif //#ifndef CONCURRENTQUEUE_H_INCLUDED
-163
View File
@@ -1,163 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef FIXED_POINT_COORDINATE_H_
#define FIXED_POINT_COORDINATE_H_
#include "../DataStructures/MercatorUtil.h"
#include "../Util/StringUtil.h"
#include <cassert>
#include <cmath>
#include <climits>
#include <iostream>
static const double COORDINATE_PRECISION = 1000000.;
struct FixedPointCoordinate {
int lat;
int lon;
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {}
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(lon) {}
void Reset() {
lat = INT_MIN;
lon = INT_MIN;
}
bool isSet() const {
return (INT_MIN != lat) && (INT_MIN != lon);
}
inline bool isValid() const {
if(
lat > 90*COORDINATE_PRECISION ||
lat < -90*COORDINATE_PRECISION ||
lon > 180*COORDINATE_PRECISION ||
lon < -180*COORDINATE_PRECISION
) {
return false;
}
return true;
}
bool operator==(const FixedPointCoordinate & other) const {
return lat == other.lat && lon == other.lon;
}
};
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
out << "(" << c.lat << "," << c.lon << ")";
return out;
}
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
assert(lat1 != INT_MIN);
assert(lon1 != INT_MIN);
assert(lat2 != INT_MIN);
assert(lon2 != INT_MIN);
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/COORDINATE_PRECISION;
double ln1 = lon1/COORDINATE_PRECISION;
double lt2 = lat2/COORDINATE_PRECISION;
double ln2 = lon2/COORDINATE_PRECISION;
double dlat1=lt1*(RAD);
double dlong1=ln1*(RAD);
double dlat2=lt2*(RAD);
double dlong2=ln2*(RAD);
double dLong=dlong1-dlong2;
double dLat=dlat1-dlat2;
double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2);
double cHarv=2.*atan2(sqrt(aHarv),sqrt(1.0-aHarv));
//earth's radius from wikipedia varies between 6,356.750 km — 6,378.135 km (˜3,949.901 — 3,963.189 miles)
//The IUGG value for the equatorial radius of the Earth is 6378.137 km (3963.19 mile)
const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km
double distance=earth*cHarv;
return distance;
}
inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
}
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
assert(c1.lat != INT_MIN);
assert(c1.lon != INT_MIN);
assert(c2.lat != INT_MIN);
assert(c2.lon != INT_MIN);
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
const double y = (lat2-lat1);
const double earthRadius = 6372797.560856;
const double d = sqrt(x*x + y*y) * earthRadius;
return d;
}
static inline void convertInternalLatLonToString(const int value, std::string & output) {
char buffer[100];
buffer[10] = 0; // Nullterminierung
char* string = printInt< 10, 6 >( buffer, value );
output = string;
}
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
std::string tmp;
convertInternalLatLonToString(coord.lon, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
output += " ";
}
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
std::string tmp;
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
output += " ";
}
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
template<class CoordinateT>
static inline double GetAngleBetweenThreeFixedPointCoordinates (
const CoordinateT & A,
const CoordinateT & C,
const CoordinateT & B
) {
const double v1x = (A.lon - C.lon)/COORDINATE_PRECISION;
const double v1y = lat2y(A.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
const double v2x = (B.lon - C.lon)/COORDINATE_PRECISION;
const double v2y = lat2y(B.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
while(angle < 0)
angle += 360;
return angle;
}
#endif /* FIXED_POINT_COORDINATE_H_ */
-318
View File
@@ -1,318 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include <cassert>
#include <vector>
#if __cplusplus > 199711L
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
#else
#define DEALLOCATION_VECTOR_NULL_PTR NULL
#endif
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
protected:
class DeallocatingVectorIteratorState {
private:
//make constructors explicit, so we do not mix random access and deallocation iterators.
DeallocatingVectorIteratorState();
public:
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
setPointerForIndex();
}
ElementT * mData;
std::size_t mIndex;
std::vector<ElementT *> & mBucketList;
inline void setPointerForIndex() {
if(bucketSizeC*mBucketList.size() <= mIndex) {
mData = DEALLOCATION_VECTOR_NULL_PTR;
return;
}
std::size_t _bucket = mIndex/bucketSizeC;
std::size_t _index = mIndex%bucketSizeC;
mData = &(mBucketList[_bucket][_index]);
if(DeallocateC) {
//if we hopped over the border of the previous bucket, then delete that bucket.
if(0 == _index && _bucket) {
delete[] mBucketList[_bucket-1];
mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
}
}
}
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
}
inline bool operator==(const DeallocatingVectorIteratorState &other) {
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
}
inline bool operator<(const DeallocatingVectorIteratorState &other) {
return mIndex < other.mIndex;
}
//This is a hack to make assignment operator possible with reference member
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
if (this != &a) {
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
new (this) DeallocatingVectorIteratorState(a); // placement new
}
return *this;
}
};
DeallocatingVectorIteratorState mState;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
DeallocatingVectorIterator() {}
template<typename T2>
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
//DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
template<typename T2>
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
if(DeallocateC) assert(false);
mState = r.mState; return *this;
}
inline DeallocatingVectorIterator& operator++() { //prefix
// if(DeallocateC) assert(false);
++mState.mIndex; mState.setPointerForIndex(); return *this;
}
inline DeallocatingVectorIterator& operator--() { //prefix
if(DeallocateC) assert(false);
--mState.mIndex; mState.setPointerForIndex(); return *this;
}
inline DeallocatingVectorIterator operator++(int) { //postfix
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex++; mState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator --(int) { //postfix
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex--; mState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex+=n; _myState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
mState.mIndex+=n; return *this;
}
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex-=n; _myState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
if(DeallocateC) assert(false);
mState.mIndex-=n; return *this;
}
inline reference operator*() const { return *mState.mData; }
inline pointer operator->() const { return mState.mData; }
inline reference operator[](const difference_type &n) const {
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex += n;
_myState.setPointerForIndex;
return _myState.mData;
}
inline bool operator!=(const DeallocatingVectorIterator & other) {
return mState != other.mState;
}
inline bool operator==(const DeallocatingVectorIterator & other) {
return mState == other.mState;
}
bool operator<(const DeallocatingVectorIterator & other) {
return mState < other.mState;
}
difference_type operator-(const DeallocatingVectorIterator & other) {
if(DeallocateC) assert(false);
return mState.mIndex-other.mState.mIndex;
}
};
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
class DeallocatingVector {
private:
std::size_t mCurrentSize;
std::vector<ElementT *> mBucketList;
public:
typedef ElementT value_type;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
DeallocatingVector() : mCurrentSize(0) {
//initial bucket
mBucketList.push_back(new ElementT[bucketSizeC]);
}
~DeallocatingVector() {
clear();
}
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
std::swap(mCurrentSize, other.mCurrentSize);
mBucketList.swap(other.mBucketList);
}
inline void clear() {
//Delete[]'ing ptr's to all Buckets
for(unsigned i = 0; i < mBucketList.size(); ++i) {
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
delete[] mBucketList[i];
mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
}
}
//Removing all ptrs from vector
std::vector<ElementT *>().swap(mBucketList);
mCurrentSize = 0;
}
inline void push_back(const ElementT & element) {
std::size_t _capacity = capacity();
if(mCurrentSize == _capacity) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
std::size_t _index = size()%bucketSizeC;
mBucketList.back()[_index] = element;
++mCurrentSize;
}
inline void reserve(const std::size_t) const {
//don't do anything
}
inline void resize(const std::size_t new_size) {
if(new_size > mCurrentSize) {
while(capacity() < new_size) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
mCurrentSize = new_size;
}
if(new_size < mCurrentSize) {
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
delete[] mBucketList[i];
}
mBucketList.resize(number_of_necessary_buckets);
mCurrentSize = new_size;
}
}
inline std::size_t size() const {
return mCurrentSize;
}
inline std::size_t capacity() const {
return mBucketList.size() * bucketSizeC;
}
inline iterator begin() {
return iterator(static_cast<std::size_t>(0), mBucketList);
}
inline iterator end() {
return iterator(size(), mBucketList);
}
inline deallocation_iterator dbegin() {
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
}
inline deallocation_iterator dend() {
return deallocation_iterator(size(), mBucketList);
}
inline const_iterator begin() const {
return const_iterator(static_cast<std::size_t>(0), mBucketList);
}
inline const_iterator end() const {
return const_iterator(size(), mBucketList);
}
inline ElementT & operator[](const std::size_t index) {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & operator[](const std::size_t index) const {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
inline ElementT & back() {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & back() const {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
};
#endif /* DEALLOCATINGVECTOR_H_ */
-233
View File
@@ -1,233 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DYNAMICGRAPH_H_INCLUDED
#define DYNAMICGRAPH_H_INCLUDED
#include "../DataStructures/DeallocatingVector.h"
#include <boost/assert.hpp>
#include <boost/integer.hpp>
#include <algorithm>
#include <limits>
#include <vector>
template< typename EdgeDataT>
class DynamicGraph {
public:
typedef EdgeDataT EdgeData;
typedef uint32_t NodeIterator;
typedef uint32_t EdgeIterator;
class InputEdge {
public:
NodeIterator source;
NodeIterator target;
EdgeDataT data;
bool operator<( const InputEdge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
};
//Constructs an empty graph with a given number of nodes.
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
m_edges.reserve( m_numNodes * 1.1 );
m_edges.resize( m_numNodes );
}
template<class ContainerT>
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
m_numNodes = nodes;
m_numEdges = ( EdgeIterator ) graph.size();
m_nodes.reserve( m_numNodes +1);
m_nodes.resize( m_numNodes +1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
EdgeIterator lastEdge = edge;
while ( edge < m_numEdges && graph[edge].source == node ) {
++edge;
}
m_nodes[node].firstEdge = position;
m_nodes[node].edges = edge - lastEdge;
position += m_nodes[node].edges;
}
m_nodes.back().firstEdge = position;
m_edges.reserve( position * 1.1 );
m_edges.resize( position );
edge = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
m_edges[i].target = graph[edge].target;
m_edges[i].data = graph[edge].data;
BOOST_ASSERT_MSG(
graph[edge].data.distance > 0,
"edge distance invalid"
);
++edge;
}
}
}
~DynamicGraph(){ }
uint32_t GetNumberOfNodes() const {
return m_numNodes;
}
uint32_t GetNumberOfEdges() const {
return m_numEdges;
}
uint32_t GetOutDegree( const NodeIterator n ) const {
return m_nodes[n].edges;
}
NodeIterator GetTarget( const EdgeIterator e ) const {
return NodeIterator( m_edges[e].target );
}
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
return m_edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
return m_edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator n ) const {
return EdgeIterator( m_nodes[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator n ) const {
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
}
//adds an edge. Invalidates edge iterators for the source node
EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) {
Node &node = m_nodes[from];
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
node.firstEdge--;
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
} else {
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
uint32_t newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
if ( requiredCapacity >= oldCapacity ) {
m_edges.reserve( requiredCapacity * 1.1 );
}
m_edges.resize( m_edges.size() + newSize );
for ( EdgeIterator i = 0; i < node.edges; ++i ) {
m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
makeDummy( node.firstEdge + i );
}
for ( EdgeIterator i = node.edges + 1; i < newSize; ++i )
makeDummy( newFirstEdge + i );
node.firstEdge = newFirstEdge;
}
}
Edge &edge = m_edges[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
++m_numEdges;
++node.edges;
return EdgeIterator( node.firstEdge + node.edges );
}
//removes an edge. Invalidates edge iterators for the source node
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
Node &node = m_nodes[source];
--m_numEdges;
--node.edges;
const uint32_t last = node.firstEdge + node.edges;
//swap with last edge
m_edges[e] = m_edges[last];
makeDummy( last );
}
//removes all edges (source,target)
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
int32_t deleted = 0;
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
if ( m_edges[i].target == target ) {
do {
deleted++;
m_edges[i] = m_edges[iend - deleted];
makeDummy( iend - deleted );
} while ( i < iend - deleted && m_edges[i].target == target );
}
}
#pragma omp atomic
m_numEdges -= deleted;
m_nodes[source].edges -= deleted;
return deleted;
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
if ( to == m_edges[i].target ) {
return i;
}
}
return EndEdges( from );
}
protected:
bool isDummy( const EdgeIterator edge ) const {
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
}
void makeDummy( const EdgeIterator edge ) {
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
}
struct Node {
//index of the first edge
EdgeIterator firstEdge;
//amount of edges
uint32_t edges;
};
struct Edge {
NodeIterator target;
EdgeDataT data;
};
NodeIterator m_numNodes;
EdgeIterator m_numEdges;
std::vector< Node > m_nodes;
DeallocatingVector< Edge > m_edges;
};
#endif // DYNAMICGRAPH_H_INCLUDED
-58
View File
@@ -1,58 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
Created on: 18.11.2010
Author: dennis
*/
#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#include <boost/ref.hpp>
#include <boost/unordered_map.hpp>
template<typename keyT, typename valueT>
class HashTable : public boost::unordered_map<keyT, valueT> {
private:
typedef boost::unordered_map<keyT, valueT> super;
public:
HashTable() : super() { }
HashTable(const unsigned size) : super(size) { }
inline void Add(const keyT& key, const valueT& value){
super::insert(std::make_pair(key, value));
}
inline valueT Find(const keyT& key) const {
if(super::find(key) == super::end()) {
return valueT();
}
return boost::ref(super::find(key)->second);
}
inline bool Holds(const keyT& key) const {
if(super::find(key) == super::end()) {
return false;
}
return true;
}
};
#endif /* HASHTABLE_H_ */
-90
View File
@@ -1,90 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef HILBERTVALUE_H_
#define HILBERTVALUE_H_
#include "Coordinate.h"
#include <boost/integer.hpp>
#include <boost/noncopyable.hpp>
// computes a 64 bit value that corresponds to the hilbert space filling curve
class HilbertCode : boost::noncopyable {
public:
static uint64_t GetHilbertNumberForCoordinate(
const FixedPointCoordinate & current_coordinate
) {
unsigned location[2];
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
TransposeCoordinate(location);
const uint64_t result = BitInterleaving(location[0], location[1]);
return result;
}
private:
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
uint64_t result = 0;
for(int8_t index = 31; index >= 0; --index){
result |= (a >> index) & 1;
result <<= 1;
result |= (b >> index) & 1;
if(0 != index){
result <<= 1;
}
}
return result;
}
static inline void TransposeCoordinate( uint32_t * X) {
uint32_t M = 1 << (32-1), P, Q, t;
int i;
// Inverse undo
for( Q = M; Q > 1; Q >>= 1 ) {
P=Q-1;
for( i = 0; i < 2; ++i ) {
if( X[i] & Q ) {
X[0] ^= P; // invert
} else {
t = (X[0]^X[i]) & P;
X[0] ^= t;
X[i] ^= t;
}
} // exchange
}
// Gray encode
for( i = 1; i < 2; ++i ) {
X[i] ^= X[i-1];
}
t=0;
for( Q = M; Q > 1; Q >>= 1 ) {
if( X[2-1] & Q ) {
t ^= Q-1;
}
} //check if this for loop is wrong
for( i = 0; i < 2; ++i ) {
X[i] ^= t;
}
}
};
#endif /* HILBERTVALUE_H_ */
-170
View File
@@ -1,170 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EDGE_H
#define EDGE_H
#include "../Util/OSRMException.h"
#include <cassert>
class NodeBasedEdge {
public:
bool operator< (const NodeBasedEdge& e) const {
if (source() == e.source()) {
if (target() == e.target()) {
if (weight() == e.weight()) {
return (isForward() && isBackward() &&
((! e.isForward()) || (! e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
explicit NodeBasedEdge(
NodeID s,
NodeID t,
NodeID n,
EdgeWeight w,
bool f,
bool b,
short ty,
bool ra,
bool ig,
bool ar,
bool cf
) : _source(s),
_target(t),
_name(n),
_weight(w),
forward(f),
backward(b),
_type(ty),
_roundabout(ra),
_ignoreInGrid(ig),
_accessRestricted(ar),
_contraFlow(cf)
{
if(ty < 0) {
throw OSRMException("negative edge type");
}
}
NodeID target() const {return _target; }
NodeID source() const {return _source; }
NodeID name() const { return _name; }
EdgeWeight weight() const {return _weight; }
short type() const { assert(_type >= 0); return _type; }
bool isBackward() const { return backward; }
bool isForward() const { return forward; }
bool isLocatable() const { return _type != 14; }
bool isRoundabout() const { return _roundabout; }
bool ignoreInGrid() const { return _ignoreInGrid; }
bool isAccessRestricted() const { return _accessRestricted; }
bool isContraFlow() const { return _contraFlow; }
NodeID _source;
NodeID _target;
NodeID _name;
EdgeWeight _weight;
bool forward;
bool backward;
short _type;
bool _roundabout;
bool _ignoreInGrid;
bool _accessRestricted;
bool _contraFlow;
private:
/** Default constructor. target and weight are set to 0.*/
NodeBasedEdge() :
_source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used.
};
class EdgeBasedEdge {
public:
bool operator< (const EdgeBasedEdge& e) const {
if (source() == e.source()) {
if (target() == e.target()) {
if (weight() == e.weight()) {
return (isForward() && isBackward() &&
((! e.isForward()) || (! e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
template<class EdgeT>
EdgeBasedEdge(const EdgeT & myEdge ) :
m_source(myEdge.source),
m_target(myEdge.target),
m_edgeID(myEdge.data.via),
m_weight(myEdge.data.distance),
m_forward(myEdge.data.forward),
m_backward(myEdge.data.backward)
{ }
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge() :
m_source(0),
m_target(0),
m_edgeID(0),
m_weight(0),
m_forward(false),
m_backward(false)
{ }
explicit EdgeBasedEdge(const NodeID s, const NodeID t, const NodeID v, const EdgeWeight w, const bool f, const bool b) :
m_source(s),
m_target(t),
m_edgeID(v),
m_weight(w),
m_forward(f),
m_backward(b)
{}
NodeID target() const {return m_target; }
NodeID source() const {return m_source; }
EdgeWeight weight() const {return m_weight; }
NodeID id() const { return m_edgeID; }
bool isBackward() const { return m_backward; }
bool isForward() const { return m_forward; }
private:
NodeID m_source;
NodeID m_target;
NodeID m_edgeID;
EdgeWeight m_weight:30;
bool m_forward:1;
bool m_backward:1;
};
typedef NodeBasedEdge ImportEdge;
#endif // EDGE_H
-54
View File
@@ -1,54 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef IMPORTNODE_H_
#define IMPORTNODE_H_
#include "QueryNode.h"
#include "../DataStructures/HashTable.h"
struct _Node : NodeInfo{
_Node(int _lat, int _lon, unsigned int _id, bool _bollard, bool _trafficLight) : NodeInfo(_lat, _lon, _id), bollard(_bollard), trafficLight(_trafficLight) {}
_Node() : bollard(false), trafficLight(false) {}
static _Node min_value() {
return _Node(0,0,0, false, false);
}
static _Node max_value() {
return _Node((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)(), (std::numeric_limits<unsigned int>::max)(), false, false);
}
NodeID key() const {
return id;
}
bool bollard;
bool trafficLight;
};
struct ImportNode : public _Node {
HashTable<std::string, std::string> keyVals;
inline void Clear() {
keyVals.clear();
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
}
};
#endif /* IMPORTNODE_H_ */
-94
View File
@@ -1,94 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef INPUTREADERFACTORY_H
#define INPUTREADERFACTORY_H
#include <bzlib.h>
#include <libxml/xmlreader.h>
struct BZ2Context {
FILE* file;
BZFILE* bz2;
int error;
int nUnused;
char unused[BZ_MAX_UNUSED];
};
int readFromBz2Stream( void* pointer, char* buffer, int len ) {
void *unusedTmpVoid=NULL;
char *unusedTmp=NULL;
BZ2Context* context = (BZ2Context*) pointer;
int read = 0;
while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) {
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
if(BZ_OK == context->error) {
return read;
} else if(BZ_STREAM_END == context->error) {
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
unusedTmp = (char*)unusedTmpVoid;
for(int i=0;i<context->nUnused;i++) {
context->unused[i] = unusedTmp[i];
}
BZ2_bzReadClose(&context->error, context->bz2);
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
if(0 == context->nUnused && feof(context->file)) {
return read;
} else {
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
}
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
}
return read;
}
int closeBz2Stream( void *pointer )
{
BZ2Context* context = (BZ2Context*) pointer;
fclose( context->file );
delete context;
return 0;
}
xmlTextReaderPtr inputReaderFactory( const char* name )
{
std::string inputName(name);
if(inputName.find(".osm.bz2")!=std::string::npos)
{
BZ2Context* context = new BZ2Context();
context->error = false;
context->file = fopen( name, "r" );
int error;
context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused );
if ( context->bz2 == NULL || context->file == NULL ) {
delete context;
return NULL;
}
return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
} else {
return xmlNewTextReaderFilename(name);
}
}
#endif // INPUTREADERFACTORY_H
-82
View File
@@ -1,82 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef LRUCACHE_H
#define LRUCACHE_H
#include <list>
#include <boost/unordered_map.hpp>
template<typename KeyT, typename ValueT>
class LRUCache {
private:
struct CacheEntry {
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
KeyT key;
ValueT value;
};
unsigned capacity;
std::list<CacheEntry> itemsInCache;
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
public:
LRUCache(unsigned c) : capacity(c) {}
bool Holds(KeyT key) {
if(positionMap.find(key) != positionMap.end()) {
return true;
}
return false;
}
void Insert(const KeyT key, ValueT &value) {
itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if(itemsInCache.size() > capacity) {
positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back();
}
}
void Insert(const KeyT key, ValueT value) {
itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if(itemsInCache.size() > capacity) {
positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back();
}
}
bool Fetch(const KeyT key, ValueT& result) {
if(Holds(key)) {
CacheEntry e = *(positionMap.find(key)->second);
result = e.value;
//move to front
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
positionMap.find(key)->second = itemsInCache.begin();
return true;
}
return false;
}
unsigned Size() const {
return itemsInCache.size();
}
};
#endif //LRUCACHE_H
-38
View File
@@ -1,38 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef MERCATORUTIL_H_
#define MERCATORUTIL_H_
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
inline double y2lat(double a) {
return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
}
inline double lat2y(double a) {
return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
}
#endif /* MERCATORUTIL_H_ */
-204
View File
@@ -1,204 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_
#include "QueryNode.h"
#include "PhantomNodes.h"
#include "StaticRTree.h"
#include "../Contractor/EdgeBasedGraphFactory.h"
#include "../Util/OSRMException.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/noncopyable.hpp>
#include <iostream>
#include <string>
#include <vector>
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
class NodeInformationHelpDesk : boost::noncopyable {
public:
NodeInformationHelpDesk(
const std::string & ramIndexInput,
const std::string & fileIndexInput,
const std::string & nodes_filename,
const std::string & edges_filename,
const unsigned number_of_nodes,
const unsigned check_sum
) : number_of_nodes(number_of_nodes), check_sum(check_sum)
{
if ( ramIndexInput.empty() ) {
throw OSRMException("no ram index file name in server ini");
}
if ( fileIndexInput.empty() ) {
throw OSRMException("no mem index file name in server ini");
}
if ( nodes_filename.empty() ) {
throw OSRMException("no nodes file name in server ini");
}
if ( edges_filename.empty() ) {
throw OSRMException("no edges file name in server ini");
}
read_only_rtree = new StaticRTree<RTreeLeaf>(
ramIndexInput,
fileIndexInput
);
BOOST_ASSERT_MSG(
0 == coordinateVector.size(),
"Coordinate vector not empty"
);
LoadNodesAndEdges(nodes_filename, edges_filename);
}
//Todo: Shared memory mechanism
~NodeInformationHelpDesk() {
delete read_only_rtree;
}
inline int getLatitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData_viaNode.at(id);
return coordinateVector.at(node).lat;
}
inline int getLongitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData_viaNode.at(id);
return coordinateVector.at(node).lon;
}
inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
return origEdgeData_nameID.at(id);
}
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
return origEdgeData_turnInstruction.at(id);
}
inline NodeID getNumberOfNodes() const {
return number_of_nodes;
}
inline NodeID getNumberOfNodes2() const {
return coordinateVector.size();
}
inline bool FindNearestNodeCoordForLatLon(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
PhantomNode resulting_phantom_node;
bool foundNode = FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node, zoom_level
);
result = resulting_phantom_node.location;
return foundNode;
}
inline bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return read_only_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
}
inline unsigned GetCheckSum() const {
return check_sum;
}
private:
void LoadNodesAndEdges(
const std::string & nodes_filename,
const std::string & edges_filename
) {
boost::filesystem::path nodes_file(nodes_filename);
if ( !boost::filesystem::exists( nodes_file ) ) {
throw OSRMException("nodes file does not exist");
}
if ( 0 == boost::filesystem::file_size( nodes_file ) ) {
throw OSRMException("nodes file is empty");
}
boost::filesystem::path edges_file(edges_filename);
if ( !boost::filesystem::exists( edges_file ) ) {
throw OSRMException("edges file does not exist");
}
if ( 0 == boost::filesystem::file_size( edges_file ) ) {
throw OSRMException("edges file is empty");
}
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
SimpleLogger().Write(logDEBUG) << "Loading node data";
NodeInfo b;
while(!nodes_input_stream.eof()) {
nodes_input_stream.read((char *)&b, sizeof(NodeInfo));
coordinateVector.push_back(FixedPointCoordinate(b.lat, b.lon));
}
std::vector<FixedPointCoordinate>(coordinateVector).swap(coordinateVector);
nodes_input_stream.close();
SimpleLogger().Write(logDEBUG) << "Loading edge data";
unsigned numberOfOrigEdges(0);
edges_input_stream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
origEdgeData_viaNode.resize(numberOfOrigEdges);
origEdgeData_nameID.resize(numberOfOrigEdges);
origEdgeData_turnInstruction.resize(numberOfOrigEdges);
OriginalEdgeData deserialized_originalEdgeData;
for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
edges_input_stream.read(
(char*)&(deserialized_originalEdgeData),
sizeof(OriginalEdgeData)
);
origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID;
origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
}
edges_input_stream.close();
SimpleLogger().Write(logDEBUG) << "Loaded " << numberOfOrigEdges << " orig edges";
SimpleLogger().Write(logDEBUG) << "Opening NN indices";
}
std::vector<FixedPointCoordinate> coordinateVector;
std::vector<NodeID> origEdgeData_viaNode;
std::vector<unsigned> origEdgeData_nameID;
std::vector<TurnInstruction> origEdgeData_turnInstruction;
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * read_only_rtree;
const unsigned number_of_nodes;
const unsigned check_sum;
};
#endif /*NODEINFORMATIONHELPDESK_H_*/
-94
View File
@@ -1,94 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PERCENT_H
#define PERCENT_H
#include "../Util/OpenMPWrapper.h"
#include <iostream>
class Percent
{
public:
/**
* Constructor.
* @param maxValue the value that corresponds to 100%
* @param step the progress is shown in steps of 'step' percent
*/
Percent(unsigned maxValue, unsigned step = 5) {
reinit(maxValue, step);
}
/** Reinitializes this object. */
void reinit(unsigned maxValue, unsigned step = 5) {
_maxValue = maxValue;
_current_value = 0;
_intervalPercent = _maxValue / 100;
_nextThreshold = _intervalPercent;
_lastPercent = 0;
_step = step;
}
/** If there has been significant progress, display it. */
void printStatus(unsigned currentValue) {
if (currentValue >= _nextThreshold) {
_nextThreshold += _intervalPercent;
printPercent( currentValue / (double)_maxValue * 100 );
}
if (currentValue + 1 == _maxValue)
std::cout << " 100%" << std::endl;
}
void printIncrement()
{
#pragma omp atomic
++_current_value;
printStatus(_current_value);
}
void printAddition(const unsigned addition) {
#pragma omp atomic
_current_value += addition;
printStatus(_current_value);
}
private:
unsigned _current_value;
unsigned _maxValue;
unsigned _intervalPercent;
unsigned _nextThreshold;
unsigned _lastPercent;
unsigned _step;
/** Displays the new progress. */
void printPercent(double percent) {
while (percent >= _lastPercent+_step) {
_lastPercent+=_step;
if (_lastPercent % 10 == 0) {
std::cout << " " << _lastPercent << "% ";
}
else {
std::cout << ".";
}
std::cout.flush();
}
}
};
#endif // PERCENT_H
-101
View File
@@ -1,101 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PHANTOMNODES_H_
#define PHANTOMNODES_H_
#include "Coordinate.h"
struct PhantomNode {
PhantomNode() :
edgeBasedNode(UINT_MAX),
nodeBasedEdgeNameID(UINT_MAX),
weight1(INT_MAX),
weight2(INT_MAX),
ratio(0.)
{ }
NodeID edgeBasedNode;
unsigned nodeBasedEdgeNameID;
int weight1;
int weight2;
double ratio;
FixedPointCoordinate location;
void Reset() {
edgeBasedNode = UINT_MAX;
nodeBasedEdgeNameID = UINT_MAX;
weight1 = INT_MAX;
weight2 = INT_MAX;
ratio = 0.;
location.Reset();
}
bool isBidirected() const {
return weight2 != INT_MAX;
}
bool isValid(const unsigned numberOfNodes) const {
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
}
bool operator==(const PhantomNode & other) const {
return location == other.location;
}
};
struct PhantomNodes {
PhantomNode startPhantom;
PhantomNode targetPhantom;
void Reset() {
startPhantom.Reset();
targetPhantom.Reset();
}
bool PhantomsAreOnSameNodeBasedEdge() const {
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
}
bool AtLeastOnePhantomNodeIsUINTMAX() const {
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
}
bool PhantomNodesHaveEqualLocation() const {
return startPhantom == targetPhantom;
}
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
out << "startCoord: " << pn.startPhantom.location << std::endl;
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
return out;
}
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
return out;
}
struct NodesOfEdge {
NodeID edgeBasedNode;
double ratio;
FixedPointCoordinate projectedPoint;
};
#endif /* PHANTOMNODES_H_ */
-67
View File
@@ -1,67 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef QUERYEDGE_H_
#define QUERYEDGE_H_
#include "TurnInstructions.h"
#include "../typedefs.h"
#include <climits>
struct OriginalEdgeData{
explicit OriginalEdgeData(
NodeID viaNode,
unsigned nameID,
TurnInstruction turnInstruction
) : viaNode(viaNode), nameID(nameID), turnInstruction(turnInstruction) {}
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
NodeID viaNode;
unsigned nameID;
TurnInstruction turnInstruction;
};
struct QueryEdge {
NodeID source;
NodeID target;
struct EdgeData {
NodeID id:31;
bool shortcut:1;
int distance:30;
bool forward:1;
bool backward:1;
} data;
bool operator<( const QueryEdge& right ) const {
if ( source != right.source ) {
return source < right.source;
}
return target < right.target;
}
bool operator== ( const QueryEdge& right ) const {
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
&& data.id == right.data.id
);
}
};
#endif /* QUERYEDGE_H_ */
-78
View File
@@ -1,78 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef _NODE_COORDS_H
#define _NODE_COORDS_H
#include "Coordinate.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <cstddef>
#include <climits>
#include <limits>
struct NodeInfo {
typedef NodeID key_type; //type of NodeID
typedef int value_type; //type of lat,lons
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
int lat;
int lon;
NodeID id;
static NodeInfo min_value() {
return NodeInfo(
-90*COORDINATE_PRECISION,
-180*COORDINATE_PRECISION,
std::numeric_limits<NodeID>::min()
);
}
static NodeInfo max_value() {
return NodeInfo(
90*COORDINATE_PRECISION,
180*COORDINATE_PRECISION,
std::numeric_limits<NodeID>::max()
);
}
value_type operator[](const std::size_t n) const {
switch(n) {
case 1:
return lat;
break;
case 0:
return lon;
break;
default:
BOOST_ASSERT_MSG(false, "should not happen");
return UINT_MAX;
break;
}
BOOST_ASSERT_MSG(false, "should not happen");
return UINT_MAX;
}
};
#endif //_NODE_COORDS_H
-49
View File
@@ -1,49 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef RAWROUTEDATA_H_
#define RAWROUTEDATA_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/PhantomNodes.h"
#include "../typedefs.h"
#include <vector>
struct _PathData {
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
NodeID node;
unsigned nameID;
unsigned durationOfSegment;
short turnInstruction;
};
struct RawRouteData {
std::vector< _PathData > computedShortestPath;
std::vector< _PathData > computedAlternativePath;
std::vector< PhantomNodes > segmentEndCoordinates;
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
unsigned checkSum;
int lengthOfShortestPath;
int lengthOfAlternativePath;
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
};
#endif /* RAWROUTEDATA_H_ */
-133
View File
@@ -1,133 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef RESTRICTION_H_
#define RESTRICTION_H_
#include "../typedefs.h"
#include <climits>
struct TurnRestriction {
NodeID viaNode;
NodeID fromNode;
NodeID toNode;
struct Bits { //mostly unused
Bits()
:
isOnly(false),
unused1(false),
unused2(false),
unused3(false),
unused4(false),
unused5(false),
unused6(false),
unused7(false)
{ }
bool isOnly:1;
bool unused1:1;
bool unused2:1;
bool unused3:1;
bool unused4:1;
bool unused5:1;
bool unused6:1;
bool unused7:1;
} flags;
TurnRestriction(NodeID viaNode) :
viaNode(viaNode),
fromNode(UINT_MAX),
toNode(UINT_MAX) {
}
TurnRestriction(const bool isOnly = false) :
viaNode(UINT_MAX),
fromNode(UINT_MAX),
toNode(UINT_MAX) {
flags.isOnly = isOnly;
}
};
struct _RawRestrictionContainer {
TurnRestriction restriction;
EdgeID fromWay;
EdgeID toWay;
unsigned viaNode;
_RawRestrictionContainer(
EdgeID fromWay,
EdgeID toWay,
NodeID vn,
unsigned vw
) :
fromWay(fromWay),
toWay(toWay),
viaNode(vw)
{
restriction.viaNode = vn;
}
_RawRestrictionContainer(
bool isOnly = false
) :
fromWay(UINT_MAX),
toWay(UINT_MAX),
viaNode(UINT_MAX)
{
restriction.flags.isOnly = isOnly;
}
static _RawRestrictionContainer min_value() {
return _RawRestrictionContainer(0, 0, 0, 0);
}
static _RawRestrictionContainer max_value() {
return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
}
};
struct CmpRestrictionContainerByFrom : public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
typedef _RawRestrictionContainer value_type;
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
return a.fromWay < b.fromWay;
}
value_type max_value() {
return _RawRestrictionContainer::max_value();
}
value_type min_value() {
return _RawRestrictionContainer::min_value();
}
};
struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
typedef _RawRestrictionContainer value_type;
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
return a.toWay < b.toWay;
}
value_type max_value() {
return _RawRestrictionContainer::max_value();
}
value_type min_value() {
return _RawRestrictionContainer::min_value();
}
};
#endif /* RESTRICTION_H_ */
-89
View File
@@ -1,89 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "SearchEngine.h"
SearchEngine::SearchEngine(
QueryGraph * g,
NodeInformationHelpDesk * nh,
std::vector<std::string> & n
) :
_queryData(g, nh, n),
shortestPath(_queryData),
alternativePaths(_queryData)
{}
SearchEngine::~SearchEngine() {}
void SearchEngine::GetCoordinatesForNodeID(
NodeID id,
FixedPointCoordinate& result
) const {
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
}
void SearchEngine::FindPhantomNodeForCoordinate(
const FixedPointCoordinate & location,
PhantomNode & result,
const unsigned zoomLevel
) const {
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
location,
result, zoomLevel
);
}
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
const NodeID s,
const NodeID t
) const {
if(s == t){
return 0;
}
EdgeID e = _queryData.graph->FindEdge(s, t);
if(e == UINT_MAX) {
e = _queryData.graph->FindEdge( t, s );
}
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
return ed.id;
}
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0);
if (is_name_invalid) {
return std::string("");
}
return HTMLEntitize(_queryData.names.at(nameID));
}
SearchEngineHeapPtr SearchEngineData::forwardHeap;
SearchEngineHeapPtr SearchEngineData::backwardHeap;
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
-68
View File
@@ -1,68 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SEARCHENGINE_H_
#define SEARCHENGINE_H_
#include "Coordinate.h"
#include "NodeInformationHelpDesk.h"
#include "PhantomNodes.h"
#include "QueryEdge.h"
#include "SearchEngineData.h"
#include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <climits>
#include <string>
#include <vector>
class SearchEngine {
private:
SearchEngineData _queryData;
public:
ShortestPathRouting<SearchEngineData> shortestPath;
AlternativeRouting<SearchEngineData> alternativePaths;
SearchEngine(
QueryGraph * g,
NodeInformationHelpDesk * nh,
std::vector<std::string> & n
);
~SearchEngine();
void GetCoordinatesForNodeID(NodeID id, FixedPointCoordinate& result) const;
void FindPhantomNodeForCoordinate(
const FixedPointCoordinate & location,
PhantomNode & result,
unsigned zoomLevel
) const;
NodeID GetNameIDForOriginDestinationNodeID(
const NodeID s, const NodeID t) const;
std::string GetEscapedNameForNameID(const unsigned nameID) const;
};
#endif /* SEARCHENGINE_H_ */
-60
View File
@@ -1,60 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "SearchEngineData.h"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
if(!forwardHeap.get()) {
forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
forwardHeap->Clear();
}
if(!backwardHeap.get()) {
backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
backwardHeap->Clear();
}
}
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
if(!forwardHeap2.get()) {
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
forwardHeap2->Clear();
}
if(!backwardHeap2.get()) {
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
backwardHeap2->Clear();
}
}
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
if(!forwardHeap3.get()) {
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
forwardHeap3->Clear();
}
if(!backwardHeap3.get()) {
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
backwardHeap3->Clear();
}
}
-60
View File
@@ -1,60 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "BinaryHeap.h"
#include "QueryEdge.h"
#include "NodeInformationHelpDesk.h"
#include "StaticGraph.h"
#include "../typedefs.h"
#include <boost/thread.hpp>
#include <string>
#include <vector>
struct _HeapData {
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
struct SearchEngineData {
typedef QueryGraph Graph;
typedef QueryHeapType QueryHeap;
SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
const QueryGraph * graph;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> & names;
static SearchEngineHeapPtr forwardHeap;
static SearchEngineHeapPtr backwardHeap;
static SearchEngineHeapPtr forwardHeap2;
static SearchEngineHeapPtr backwardHeap2;
static SearchEngineHeapPtr forwardHeap3;
static SearchEngineHeapPtr backwardHeap3;
void InitializeOrClearFirstThreadLocalStorage();
void InitializeOrClearSecondThreadLocalStorage();
void InitializeOrClearThirdThreadLocalStorage();
};
-43
View File
@@ -1,43 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SEGMENTINFORMATION_H_
#define SEGMENTINFORMATION_H_
#include "TurnInstructions.h"
#include "../typedefs.h"
#include <climits>
struct SegmentInformation {
FixedPointCoordinate location;
NodeID nameID;
double length;
unsigned duration;
double bearing;
TurnInstruction turnInstruction;
bool necessary;
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
};
#endif /* SEGMENTINFORMATION_H_ */
-71
View File
@@ -1,71 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SIMPLESTACK_H_
#define SIMPLESTACK_H_
#include <cassert>
#include <vector>
template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
class SimpleStack {
private:
int last;
ContainerT arr;
public:
SimpleStack() : last(-1) {
}
SimpleStack(std::size_t size_hint) : last(-1) {
hint(size_hint);
}
inline void hint(std::size_t size_hint) {
arr.reserve(size_hint);
}
inline void push(StackItemT t) {
++last;
arr.push_back(t);
}
inline void pop() {
arr.pop_back();
--last;
}
inline StackItemT top() {
assert (last >= 0);
return arr[last];
}
inline int size() {
return last+1;
}
inline bool empty() {
return (-1 == last);
}
};
#endif /* SIMPLESTACK_H_ */
-193
View File
@@ -1,193 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef STATICGRAPH_H_INCLUDED
#define STATICGRAPH_H_INCLUDED
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <algorithm>
#include <vector>
template< typename EdgeDataT>
class StaticGraph {
public:
typedef NodeID NodeIterator;
typedef NodeID EdgeIterator;
typedef EdgeDataT EdgeData;
class InputEdge {
public:
EdgeDataT data;
NodeIterator source;
NodeIterator target;
bool operator<( const InputEdge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
};
struct _StrNode {
//index of the first edge
EdgeIterator firstEdge;
};
struct _StrEdge {
NodeID target;
EdgeDataT data;
};
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
std::sort( graph.begin(), graph.end() );
_numNodes = nodes;
_numEdges = ( EdgeIterator ) graph.size();
_nodes.resize( _numNodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
EdgeIterator lastEdge = edge;
while ( edge < _numEdges && graph[edge].source == node )
++edge;
_nodes[node].firstEdge = position; //=edge
position += edge - lastEdge; //remove
}
_edges.resize( position ); //(edge)
edge = 0;
for ( NodeIterator node = 0; node < _numNodes; ++node ) {
for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
_edges[i].target = graph[edge].target;
_edges[i].data = graph[edge].data;
assert(_edges[i].data.distance > 0);
edge++;
}
}
}
StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
_numNodes = nodes.size();
_numEdges = edges.size();
_nodes.swap(nodes);
_edges.swap(edges);
//Add dummy node to end of _nodes array;
_nodes.push_back(_nodes.back());
#ifndef NDEBUG
Percent p(GetNumberOfNodes());
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) {
unsigned v = GetTarget(eid);
EdgeData & data = GetEdgeData(eid);
if(data.shortcut) {
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find first segment of edge (" <<
u << "," << data.id << "," << v << ")";
data.shortcut = false;
}
eid2 = FindEdgeInEitherDirection(data.id, v);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find second segment of edge (" <<
u << "," << data.id << "," << v << ")";
data.shortcut = false;
}
}
}
p.printIncrement();
}
#endif
}
unsigned GetNumberOfNodes() const {
return _numNodes;
}
unsigned GetNumberOfEdges() const {
return _numEdges;
}
unsigned GetOutDegree( const NodeIterator &n ) const {
return BeginEdges(n)-EndEdges(n) - 1;
}
inline NodeIterator GetTarget( const EdgeIterator &e ) const {
return NodeIterator( _edges[e].target );
}
inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
return _edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
return _edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator &n ) const {
return EdgeIterator( _nodes[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator &n ) const {
return EdgeIterator( _nodes[n+1].firstEdge );
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator smallestEdge = SPECIAL_EDGEID;
EdgeWeight smallestWeight = UINT_MAX;
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
const NodeID target = GetTarget(edge);
const EdgeWeight weight = GetEdgeData(edge).distance;
if(target == to && weight < smallestWeight) {
smallestEdge = edge; smallestWeight = weight;
}
}
return smallestEdge;
}
EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator tmp = FindEdge( from, to );
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
}
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
EdgeIterator tmp = FindEdge( from, to );
if(UINT_MAX == tmp) {
tmp = FindEdge( to, from );
if(UINT_MAX != tmp)
result = true;
}
return tmp;
}
private:
NodeIterator _numNodes;
EdgeIterator _numEdges;
std::vector< _StrNode > _nodes;
std::vector< _StrEdge > _edges;
};
#endif // STATICGRAPH_H_INCLUDED
-223
View File
@@ -1,223 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
KD Tree coded by Christian Vetter, Monav Project
*/
#ifndef STATICKDTREE_H_INCLUDED
#define STATICKDTREE_H_INCLUDED
#include <cassert>
#include <vector>
#include <algorithm>
#include <stack>
#include <limits>
namespace KDTree {
#define KDTREE_BASESIZE (8)
template< unsigned k, typename T >
class BoundingBox {
public:
BoundingBox() {
for ( unsigned dim = 0; dim < k; ++dim ) {
min[dim] = std::numeric_limits< T >::min();
max[dim] = std::numeric_limits< T >::max();
}
}
T min[k];
T max[k];
};
struct NoData {};
template< unsigned k, typename T >
class EuclidianMetric {
public:
double operator() ( const T left[k], const T right[k] ) {
double result = 0;
for ( unsigned i = 0; i < k; ++i ) {
double temp = (double)left[i] - (double)right[i];
result += temp * temp;
}
return result;
}
double operator() ( const BoundingBox< k, T > &box, const T point[k] ) {
T nearest[k];
for ( unsigned dim = 0; dim < k; ++dim ) {
if ( point[dim] < box.min[dim] )
nearest[dim] = box.min[dim];
else if ( point[dim] > box.max[dim] )
nearest[dim] = box.max[dim];
else
nearest[dim] = point[dim];
}
return operator() ( point, nearest );
}
};
template < unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric< k, T > >
class StaticKDTree {
public:
struct InputPoint {
T coordinates[k];
Data data;
bool operator==( const InputPoint& right )
{
for ( int i = 0; i < k; i++ ) {
if ( coordinates[i] != right.coordinates[i] )
return false;
}
return true;
}
};
StaticKDTree( std::vector< InputPoint > * points ){
assert( k > 0 );
assert ( points->size() > 0 );
size = points->size();
kdtree = new InputPoint[size];
for ( Iterator i = 0; i != size; ++i ) {
kdtree[i] = points->at(i);
for ( unsigned dim = 0; dim < k; ++dim ) {
if ( kdtree[i].coordinates[dim] < boundingBox.min[dim] )
boundingBox.min[dim] = kdtree[i].coordinates[dim];
if ( kdtree[i].coordinates[dim] > boundingBox.max[dim] )
boundingBox.max[dim] = kdtree[i].coordinates[dim];
}
}
std::stack< Tree > s;
s.push ( Tree ( 0, size, 0 ) );
while ( !s.empty() ) {
Tree tree = s.top();
s.pop();
if ( tree.right - tree.left < KDTREE_BASESIZE )
continue;
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) );
s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) );
}
}
~StaticKDTree(){
delete[] kdtree;
}
bool NearestNeighbor( InputPoint* result, const InputPoint& point ) {
Metric distance;
bool found = false;
double nearestDistance = std::numeric_limits< T >::max();
std::stack< NNTree > s;
s.push ( NNTree ( 0, size, 0, boundingBox ) );
while ( !s.empty() ) {
NNTree tree = s.top();
s.pop();
if ( distance( tree.box, point.coordinates ) >= nearestDistance )
continue;
if ( tree.right - tree.left < KDTREE_BASESIZE ) {
for ( unsigned i = tree.left; i < tree.right; i++ ) {
double newDistance = distance( kdtree[i].coordinates, point.coordinates );
if ( newDistance < nearestDistance ) {
nearestDistance = newDistance;
*result = kdtree[i];
found = true;
}
}
continue;
}
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
double newDistance = distance( kdtree[middle].coordinates, point.coordinates );
if ( newDistance < nearestDistance ) {
nearestDistance = newDistance;
*result = kdtree[middle];
found = true;
}
Less comperator( tree.dimension );
if ( !comperator( point, kdtree[middle] ) ) {
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push( second );
s.push( first );
}
else {
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push( first );
s.push( second );
}
}
return found;
}
private:
typedef unsigned Iterator;
struct Tree {
Iterator left;
Iterator right;
unsigned dimension;
Tree() {}
Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {}
};
struct NNTree {
Iterator left;
Iterator right;
unsigned dimension;
BoundingBox< k, T > box;
NNTree() {}
NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {}
};
class Less {
public:
Less( unsigned d ) {
dimension = d;
assert( dimension < k );
}
bool operator() ( const InputPoint& left, const InputPoint& right ) {
assert( dimension < k );
return left.coordinates[dimension] < right.coordinates[dimension];
}
private:
unsigned dimension;
};
BoundingBox< k, T > boundingBox;
InputPoint* kdtree;
Iterator size;
};
}
#endif // STATICKDTREE_H_INCLUDED
-832
View File
@@ -1,832 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef STATICRTREE_H_
#define STATICRTREE_H_
#include "MercatorUtil.h"
#include "Coordinate.h"
#include "PhantomNodes.h"
#include "DeallocatingVector.h"
#include "HilbertValue.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/algorithm/minmax.hpp>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <cassert>
#include <cfloat>
#include <climits>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
//tuning parameters
const static uint32_t RTREE_BRANCHING_FACTOR = 50;
const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
// Implements a static, i.e. packed, R-tree
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
template<class DataT>
class StaticRTree : boost::noncopyable {
private:
struct RectangleInt2D {
RectangleInt2D() :
min_lon(INT_MAX),
max_lon(INT_MIN),
min_lat(INT_MAX),
max_lat(INT_MIN) {}
int32_t min_lon, max_lon;
int32_t min_lat, max_lat;
inline void InitializeMBRectangle(
const DataT * objects,
const uint32_t element_count
) {
for(uint32_t i = 0; i < element_count; ++i) {
min_lon = std::min(
min_lon, std::min(objects[i].lon1, objects[i].lon2)
);
max_lon = std::max(
max_lon, std::max(objects[i].lon1, objects[i].lon2)
);
min_lat = std::min(
min_lat, std::min(objects[i].lat1, objects[i].lat2)
);
max_lat = std::max(
max_lat, std::max(objects[i].lat1, objects[i].lat2)
);
}
}
inline void AugmentMBRectangle(const RectangleInt2D & other) {
min_lon = std::min(min_lon, other.min_lon);
max_lon = std::max(max_lon, other.max_lon);
min_lat = std::min(min_lat, other.min_lat);
max_lat = std::max(max_lat, other.max_lat);
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoints are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (min_lon + max_lon)/2;
centroid.lat = (min_lat + max_lat)/2;
return centroid;
}
inline bool Intersects(const RectangleInt2D & other) const {
FixedPointCoordinate upper_left (other.max_lat, other.min_lon);
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
return (
Contains(upper_left)
|| Contains(upper_right)
|| Contains(lower_right)
|| Contains(lower_left)
);
}
inline double GetMinDist(const FixedPointCoordinate & location) const {
bool is_contained = Contains(location);
if (is_contained) {
return 0.0;
}
double min_dist = DBL_MAX;
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
max_lat,
min_lon
)
);
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
max_lat,
max_lon
)
);
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
min_lat,
max_lon
)
);
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
min_lat,
min_lon
)
);
return min_dist;
}
inline double GetMinMaxDist(const FixedPointCoordinate & location) const {
double min_max_dist = DBL_MAX;
//Get minmax distance to each of the four sides
FixedPointCoordinate upper_left (max_lat, min_lon);
FixedPointCoordinate upper_right(max_lat, max_lon);
FixedPointCoordinate lower_right(min_lat, max_lon);
FixedPointCoordinate lower_left (min_lat, min_lon);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, upper_left ),
ApproximateDistance(location, upper_right)
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, upper_right),
ApproximateDistance(location, lower_right)
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, lower_right),
ApproximateDistance(location, lower_left )
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, lower_left ),
ApproximateDistance(location, upper_left )
)
);
return min_max_dist;
}
inline bool Contains(const FixedPointCoordinate & location) const {
bool lats_contained =
(location.lat > min_lat) && (location.lat < max_lat);
bool lons_contained =
(location.lon > min_lon) && (location.lon < max_lon);
return lats_contained && lons_contained;
}
inline friend std::ostream & operator<< (
std::ostream & out,
const RectangleInt2D & rect
) {
out << rect.min_lat/COORDINATE_PRECISION << ","
<< rect.min_lon/COORDINATE_PRECISION << " "
<< rect.max_lat/COORDINATE_PRECISION << ","
<< rect.max_lon/COORDINATE_PRECISION;
return out;
}
};
typedef RectangleInt2D RectangleT;
struct WrappedInputElement {
explicit WrappedInputElement(
const uint32_t _array_index,
const uint64_t _hilbert_value
) : m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
uint32_t m_array_index;
uint64_t m_hilbert_value;
inline bool operator<(const WrappedInputElement & other) const {
return m_hilbert_value < other.m_hilbert_value;
}
};
struct LeafNode {
LeafNode() : object_count(0) {}
uint32_t object_count;
DataT objects[RTREE_LEAF_NODE_SIZE];
};
struct TreeNode {
TreeNode() : child_count(0), child_is_on_disk(false) {}
RectangleT minimum_bounding_rectangle;
uint32_t child_count:31;
bool child_is_on_disk:1;
uint32_t children[RTREE_BRANCHING_FACTOR];
};
struct QueryCandidate {
explicit QueryCandidate(
const uint32_t n_id,
const double dist
) : node_id(n_id), min_dist(dist) {}
QueryCandidate() : node_id(UINT_MAX), min_dist(DBL_MAX) {}
uint32_t node_id;
double min_dist;
inline bool operator<(const QueryCandidate & other) const {
return min_dist < other.min_dist;
}
};
std::vector<TreeNode> m_search_tree;
uint64_t m_element_count;
const std::string m_leaf_node_filename;
public:
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
explicit StaticRTree(
std::vector<DataT> & input_data_vector,
const std::string tree_node_filename,
const std::string leaf_node_filename
)
: m_element_count(input_data_vector.size()),
m_leaf_node_filename(leaf_node_filename)
{
SimpleLogger().Write() <<
"constructing r-tree of " << m_element_count <<
" elements";
double time1 = get_timestamp();
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
//generate auxiliary vector of hilbert-values
#pragma omp parallel for schedule(guided)
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
input_wrapper_vector[element_counter].m_array_index = element_counter;
//Get Hilbert-Value for centroid in mercartor projection
DataT & current_element = input_data_vector[element_counter];
FixedPointCoordinate current_centroid = current_element.Centroid();
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
}
//open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
//sort the hilbert-value representatives
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
std::vector<TreeNode> tree_nodes_in_level;
//pack M elements into leaf node and write to leaf file
uint64_t processed_objects_count = 0;
while(processed_objects_count < m_element_count) {
LeafNode current_leaf;
TreeNode current_node;
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
if(m_element_count > (processed_objects_count + current_element_index)) {
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
++current_leaf.object_count;
}
}
//generate tree node that resemble the objects in leaf and store it for next level
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
current_node.child_is_on_disk = true;
current_node.children[0] = tree_nodes_in_level.size();
tree_nodes_in_level.push_back(current_node);
//write leaf_node to leaf node file
leaf_node_file.write((char*)&current_leaf, sizeof(current_leaf));
processed_objects_count += current_leaf.object_count;
}
//close leaf file
leaf_node_file.close();
uint32_t processing_level = 0;
while(1 < tree_nodes_in_level.size()) {
std::vector<TreeNode> tree_nodes_in_next_level;
uint32_t processed_tree_nodes_in_level = 0;
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
TreeNode parent_node;
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
for(
uint32_t current_child_node_index = 0;
RTREE_BRANCHING_FACTOR > current_child_node_index;
++current_child_node_index
) {
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
//add tree node to parent entry
parent_node.children[current_child_node_index] = m_search_tree.size();
m_search_tree.push_back(current_child_node);
//augment MBR of parent
parent_node.minimum_bounding_rectangle.AugmentMBRectangle(current_child_node.minimum_bounding_rectangle);
//increase counters
++parent_node.child_count;
++processed_tree_nodes_in_level;
}
}
tree_nodes_in_next_level.push_back(parent_node);
}
tree_nodes_in_level.swap(tree_nodes_in_next_level);
++processing_level;
}
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
//last remaining entry is the root node, store it
m_search_tree.push_back(tree_nodes_in_level[0]);
//reverse and renumber tree to have root at index 0
std::reverse(m_search_tree.begin(), m_search_tree.end());
#pragma omp parallel for schedule(guided)
for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
TreeNode & current_tree_node = m_search_tree[i];
for(uint32_t j = 0; j < current_tree_node.child_count; ++j) {
const uint32_t old_id = current_tree_node.children[j];
const uint32_t new_id = m_search_tree.size() - old_id - 1;
current_tree_node.children[j] = new_id;
}
}
//open tree file
boost::filesystem::ofstream tree_node_file(
tree_node_filename,
std::ios::binary
);
uint32_t size_of_tree = m_search_tree.size();
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode)*size_of_tree);
//close tree node file.
tree_node_file.close();
double time2 = get_timestamp();
SimpleLogger().Write() <<
"finished r-tree construction in " << (time2-time1) << " seconds";
}
//Read-only operation for queries
explicit StaticRTree(
const std::string & node_filename,
const std::string & leaf_filename
) : m_leaf_node_filename(leaf_filename) {
//open tree node file and load into RAM.
boost::filesystem::path node_file(node_filename);
if ( !boost::filesystem::exists( node_file ) ) {
throw OSRMException("ram index file does not exist");
}
if ( 0 == boost::filesystem::file_size( node_file ) ) {
throw OSRMException("ram index file is empty");
}
boost::filesystem::ifstream tree_node_file( node_file, std::ios::binary );
uint32_t tree_size = 0;
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
m_search_tree.resize(tree_size);
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
tree_node_file.close();
//open leaf node file and store thread specific pointer
boost::filesystem::path leaf_file(leaf_filename);
if ( !boost::filesystem::exists( leaf_file ) ) {
throw OSRMException("mem index file does not exist");
}
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
throw OSRMException("mem index file is empty");
}
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
leaf_node_file.close();
//SimpleLogger().Write() << tree_size << " nodes in search tree";
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
/*
inline void FindKNearestPhantomNodesForCoordinate(
const FixedPointCoordinate & location,
const unsigned zoom_level,
const unsigned candidate_count,
std::vector<std::pair<PhantomNode, double> > & result_vector
) const {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0;
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = DBL_MAX;
double min_max_dist = DBL_MAX;
bool found_a_nearest_edge = false;
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
++explored_tree_nodes_count;
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
++io_count;
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue;
}
double current_ratio = 0.;
double current_perpendicular_distance = ComputePerpendicularDistance(
input_coordinate,
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
nearest,
&current_ratio
);
if(
current_perpendicular_distance < min_dist
&& !DoubleEpsilonCompare(
current_perpendicular_distance,
min_dist
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id;
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
result_phantom_node.weight1 = current_edge.weight;
result_phantom_node.weight2 = INT_MAX;
result_phantom_node.location = nearest;
current_start_coordinate.lat = current_edge.lat1;
current_start_coordinate.lon = current_edge.lon1;
current_end_coordinate.lat = current_edge.lat2;
current_end_coordinate.lon = current_edge.lon2;
nearest_edge = current_edge;
found_a_nearest_edge = true;
} else if(
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
&& CoordinatesAreEquivalent(
current_start_coordinate,
FixedPointCoordinate(
current_edge.lat1,
current_edge.lon1
),
FixedPointCoordinate(
current_edge.lat2,
current_edge.lon2
),
current_end_coordinate
)
) {
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
result_phantom_node.weight2 = current_edge.weight;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
TreeNode & child_tree_node = m_search_tree[child_id];
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if (current_min_dist > min_max_dist) {
continue;
}
if (current_min_dist > min_dist) { //upward pruning
continue;
}
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
}
}
}
}
const double distance_to_edge =
ApproximateDistance (
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
result_phantom_node.location
);
const double length_of_edge =
ApproximateDistance(
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
);
const double ratio = (found_a_nearest_edge ?
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
result_phantom_node.weight1 *= ratio;
if(INT_MAX != result_phantom_node.weight2) {
result_phantom_node.weight2 *= (1.-ratio);
}
result_phantom_node.ratio = ratio;
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon;
}
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
result_phantom_node.location.lat = input_coordinate.lat;
}
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
return found_a_nearest_edge;
}
*/
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & result_phantom_node,
const unsigned zoom_level
) {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0;
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = DBL_MAX;
double min_max_dist = DBL_MAX;
bool found_a_nearest_edge = false;
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
traversal_queue.push(
QueryCandidate(0, current_min_dist)
);
BOOST_ASSERT_MSG(
FLT_EPSILON > (0. - traversal_queue.top().min_dist),
"Root element in NN Search has min dist != 0."
);
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
++explored_tree_nodes_count;
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
++io_count;
//SimpleLogger().Write() << "checking " << current_leaf_node.object_count << " elements";
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue;
}
if(current_edge.isIgnored()) {
continue;
}
double current_ratio = 0.;
double current_perpendicular_distance = ComputePerpendicularDistance(
input_coordinate,
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
nearest,
&current_ratio
);
if(
current_perpendicular_distance < min_dist
&& !DoubleEpsilonCompare(
current_perpendicular_distance,
min_dist
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id;
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
result_phantom_node.weight1 = current_edge.weight;
result_phantom_node.weight2 = INT_MAX;
result_phantom_node.location = nearest;
current_start_coordinate.lat = current_edge.lat1;
current_start_coordinate.lon = current_edge.lon1;
current_end_coordinate.lat = current_edge.lat2;
current_end_coordinate.lon = current_edge.lon2;
nearest_edge = current_edge;
found_a_nearest_edge = true;
} else if(
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
&& CoordinatesAreEquivalent(
current_start_coordinate,
FixedPointCoordinate(
current_edge.lat1,
current_edge.lon1
),
FixedPointCoordinate(
current_edge.lat2,
current_edge.lon2
),
current_end_coordinate
)
) {
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
//SimpleLogger().Write() << "found bidirected edge on nodes " << current_edge.id << " and " << result_phantom_node.edgeBasedNode;
result_phantom_node.weight2 = current_edge.weight;
if(current_edge.id < result_phantom_node.edgeBasedNode) {
result_phantom_node.edgeBasedNode = current_edge.id;
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
std::swap(current_end_coordinate, current_start_coordinate);
// SimpleLogger().Write() <<"case 2";
}
//SimpleLogger().Write() << "w1: " << result_phantom_node.weight1 << ", w2: " << result_phantom_node.weight2;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
TreeNode & child_tree_node = m_search_tree[child_id];
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if (current_min_dist > min_max_dist) {
continue;
}
if (current_min_dist > min_dist) { //upward pruning
continue;
}
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
}
}
}
}
const double ratio = (found_a_nearest_edge ?
std::min(1., ApproximateDistance(current_start_coordinate,
result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate)
) : 0
);
result_phantom_node.weight1 *= ratio;
if(INT_MAX != result_phantom_node.weight2) {
result_phantom_node.weight2 *= (1.-ratio);
}
result_phantom_node.ratio = ratio;
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon;
}
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
result_phantom_node.location.lat = input_coordinate.lat;
}
return found_a_nearest_edge;
}
private:
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
if(!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open()) {
thread_local_rtree_stream.reset(
new boost::filesystem::ifstream(
m_leaf_node_filename,
std::ios::in | std::ios::binary
)
);
}
if(!thread_local_rtree_stream->good()) {
thread_local_rtree_stream->clear(std::ios::goodbit);
SimpleLogger().Write(logDEBUG) << "Resetting stale filestream";
}
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
thread_local_rtree_stream->seekg(seek_pos);
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
}
inline double ComputePerpendicularDistance(
const FixedPointCoordinate& inputPoint,
const FixedPointCoordinate& source,
const FixedPointCoordinate& target,
FixedPointCoordinate& nearest, double *r) const {
const double x = static_cast<double>(inputPoint.lat);
const double y = static_cast<double>(inputPoint.lon);
const double a = static_cast<double>(source.lat);
const double b = static_cast<double>(source.lon);
const double c = static_cast<double>(target.lat);
const double d = static_cast<double>(target.lon);
double p,q,mX,nY;
if(fabs(a-c) > FLT_EPSILON){
const double m = (d-b)/(c-a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
q = b + m*(p - a);
} else {
p = c;
q = y;
}
nY = (d*p - c*q)/(a*d - b*c);
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if(std::isnan(mX)) {
*r = (target == inputPoint) ? 1. : 0.;
} else {
*r = mX;
}
if(*r<=0.){
nearest.lat = source.lat;
nearest.lon = source.lon;
return ((b - y)*(b - y) + (a - x)*(a - x));
// return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x)));
} else if(*r >= 1.){
nearest.lat = target.lat;
nearest.lon = target.lon;
return ((d - y)*(d - y) + (c - x)*(c - x));
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
}
// point lies in between
nearest.lat = p;
nearest.lon = q;
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
return (p-x)*(p-x) + (q-y)*(q-y);
}
inline bool CoordinatesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const {
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
return (std::fabs(d1 - d2) < FLT_EPSILON);
}
};
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
#endif /* STATICRTREE_H_ */
-90
View File
@@ -1,90 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TURNINSTRUCTIONS_H_
#define TURNINSTRUCTIONS_H_
#include <boost/noncopyable.hpp>
typedef unsigned char TurnInstruction;
//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass : boost::noncopyable {
const static TurnInstruction NoTurn = 0; //Give no instruction at all
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
const static TurnInstruction TurnSlightRight = 2;
const static TurnInstruction TurnRight = 3;
const static TurnInstruction TurnSharpRight = 4;
const static TurnInstruction UTurn = 5;
const static TurnInstruction TurnSharpLeft = 6;
const static TurnInstruction TurnLeft = 7;
const static TurnInstruction TurnSlightLeft = 8;
const static TurnInstruction ReachViaPoint = 9;
const static TurnInstruction HeadOn = 10;
const static TurnInstruction EnterRoundAbout = 11;
const static TurnInstruction LeaveRoundAbout = 12;
const static TurnInstruction StayOnRoundAbout = 13;
const static TurnInstruction StartAtEndOfStreet = 14;
const static TurnInstruction ReachedYourDestination = 15;
const static TurnInstruction EnterAgainstAllowedDirection = 16;
const static TurnInstruction LeaveAgainstAllowedDirection = 17;
const static TurnInstruction AccessRestrictionFlag = 128;
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
if(angle >= 23 && angle < 67) {
return TurnSharpRight;
}
if (angle >= 67 && angle < 113) {
return TurnRight;
}
if (angle >= 113 && angle < 158) {
return TurnSlightRight;
}
if (angle >= 158 && angle < 202) {
return GoStraight;
}
if (angle >= 202 && angle < 248) {
return TurnSlightLeft;
}
if (angle >= 248 && angle < 292) {
return TurnLeft;
}
if (angle >= 292 && angle < 336) {
return TurnSharpLeft;
}
return UTurn;
}
static inline bool TurnIsNecessary ( const short turnInstruction ) {
if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
return false;
return true;
}
};
static TurnInstructionsClass TurnInstructions;
#endif /* TURNINSTRUCTIONS_H_ */
-95
View File
@@ -1,95 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef FASTXORHASH_H_
#define FASTXORHASH_H_
#include <algorithm>
#include <vector>
/*
This is an implementation of Tabulation hashing, which has suprising properties like universality.
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
1: movq table2(%rip), %rdx
2: movl %edi, %eax
3: movzwl %di, %edi
4: shrl $16, %eax
5: movzwl %ax, %eax
6: movzbl (%rdx,%rax), %eax
7: movq table1(%rip), %rdx
8: xorb (%rdx,%rdi), %al
9: movzbl %al, %eax
10: ret
*/
class XORFastHash { //65k entries
std::vector<unsigned short> table1;
std::vector<unsigned short> table2;
public:
XORFastHash() {
table1.resize(2 << 16);
table2.resize(2 << 16);
for(unsigned i = 0; i < (2 << 16); ++i) {
table1[i] = i; table2[i] = i;
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
}
inline unsigned short operator()(const unsigned originalValue) const {
unsigned short lsb = ((originalValue) & 0xffff);
unsigned short msb = (((originalValue) >> 16) & 0xffff);
return table1[lsb] ^ table2[msb];
}
};
class XORMiniHash { //256 entries
std::vector<unsigned char> table1;
std::vector<unsigned char> table2;
std::vector<unsigned char> table3;
std::vector<unsigned char> table4;
public:
XORMiniHash() {
table1.resize(1 << 8);
table2.resize(1 << 8);
table3.resize(1 << 8);
table4.resize(1 << 8);
for(unsigned i = 0; i < (1 << 8); ++i) {
table1[i] = i; table2[i] = i;
table3[i] = i; table4[i] = i;
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
std::random_shuffle(table3.begin(), table3.end());
std::random_shuffle(table4.begin(), table4.end());
}
unsigned char operator()(const unsigned originalValue) const {
unsigned char byte1 = ((originalValue) & 0xff);
unsigned char byte2 = ((originalValue >> 8) & 0xff);
unsigned char byte3 = ((originalValue >> 16) & 0xff);
unsigned char byte4 = ((originalValue >> 24) & 0xff);
return table1[byte1] ^ table2[byte2] ^ table3[byte3] ^ table4[byte4];
}
};
#endif /* FASTXORHASH_H_ */
-80
View File
@@ -1,80 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef XORFASTHASHSTORAGE_H_
#define XORFASTHASHSTORAGE_H_
#include "XORFastHash.h"
#include <climits>
#include <vector>
#include <bitset>
template< typename NodeID, typename Key >
class XORFastHashStorage {
public:
struct HashCell{
Key key;
NodeID id;
unsigned time;
HashCell() : key(UINT_MAX), id(UINT_MAX), time(UINT_MAX) {}
HashCell(const HashCell & other) : key(other.key), id(other.id), time(other.time) { }
inline operator Key() const {
return key;
}
inline void operator=(const Key & keyToInsert) {
key = keyToInsert;
}
};
XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
inline HashCell& operator[]( const NodeID node ) {
unsigned short position = fastHash(node);
while((positions[position].time == currentTimestamp) && (positions[position].id != node)){
++position %= (2<<16);
}
positions[position].id = node;
positions[position].time = currentTimestamp;
return positions[position];
}
inline void Clear() {
++currentTimestamp;
if(UINT_MAX == currentTimestamp) {
positions.clear();
positions.resize((2<<16));
}
}
private:
XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {}
std::vector<HashCell> positions;
XORFastHash fastHash;
unsigned currentTimestamp;
};
#endif /* XORFASTHASHSTORAGE_H_ */
-56
View File
@@ -1,56 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASE_DESCRIPTOR_H_
#define BASE_DESCRIPTOR_H_
#include "../DataStructures/HashTable.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngine.h"
#include "../Server/BasicDatastructures.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <cassert>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
struct _DescriptorConfig {
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
bool instructions;
bool geometry;
bool encodeGeometry;
unsigned short z;
};
class BaseDescriptor {
public:
BaseDescriptor() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { }
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
};
#endif /* BASE_DESCRIPTOR_H_ */
-213
View File
@@ -1,213 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() : entireLength(0) { }
DescriptionFactory::~DescriptionFactory() { }
inline double DescriptionFactory::DegreeToRadian(const double degree) const {
return degree * (M_PI/180);
}
inline double DescriptionFactory::RadianToDegree(const double radian) const {
return radian * (180/M_PI);
}
double DescriptionFactory::GetBearing(
const FixedPointCoordinate & A,
const FixedPointCoordinate & B
) const {
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
double y = sin(deltaLong) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
double result = RadianToDegree(atan2(y, x));
while(result <= 0.)
result += 360.;
while(result >= 360.)
result -= 360.;
return result;
}
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
startPhantom = _startPhantom;
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
}
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
targetPhantom = _targetPhantom;
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
}
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data ) {
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
pathDescription.back().nameID = data.nameID;
} else {
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
}
}
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
if(isEncoded)
pc.printEncodedString(pathDescription, output);
else
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
pc.printEncodedString(pathDescription, output);
}
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
if(0 == pathDescription.size())
return;
// unsigned entireLength = 0;
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
}
double lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
std::string string1;
/*Simplify turn instructions
Input :
10. Turn left on B 36 for 20 km
11. Continue on B 35; B 36 for 2 km
12. Continue on B 36 for 13 km
becomes:
10. Turn left on B 36 for 35 km
*/
//TODO: rework to check only end and start of string.
// stl string is way to expensive
// unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
// if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1)
// ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// } else if(std::string::npos != string1.find(string0+";")
// || std::string::npos != string1.find(";"+string0)
// || std::string::npos != string1.find(string0+" ;")
// || std::string::npos != string1.find("; "+string0)
// ){
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// pathDescription[i].nameID = pathDescription[i-1].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// }
// }
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
// lastTurn = i;
// }
// string0 = string1;
// }
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
lengthOfSegment += pathDescription[i].length;
durationOfSegment += pathDescription[i].duration;
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
}
}
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
//Post-processing to remove empty or nearly empty path segments
if(FLT_EPSILON > pathDescription.back().length) {
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
// SimpleLogger().Write() << "Deleting last turn instruction";
}
} else {
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
}
if(FLT_EPSILON > pathDescription[0].length) {
//TODO: this is never called actually?
if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin());
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
pathDescription[0].necessary = true;
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
}
} else {
pathDescription[0].duration *= startPhantom.ratio;
}
//Generalize poly line
dp.Run(pathDescription, zoomLevel);
//fix what needs to be fixed else
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
if(pathDescription[i].necessary) {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
pathDescription[i].bearing = angle;
}
}
// BuildRouteSummary(entireLength, duration);
return;
}
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
summary.startName = startPhantom.nodeBasedEdgeNameID;
summary.destName = targetPhantom.nodeBasedEdgeNameID;
summary.BuildDurationAndLengthStrings(distance, time);
}
-77
View File
@@ -1,77 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DESCRIPTIONFACTORY_H_
#define DESCRIPTIONFACTORY_H_
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/SearchEngine.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <vector>
/* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */
class DescriptionFactory {
DouglasPeucker<SegmentInformation> dp;
PolylineCompressor pc;
PhantomNode startPhantom, targetPhantom;
double DegreeToRadian(const double degree) const;
double RadianToDegree(const double degree) const;
public:
struct _RouteSummary {
std::string lengthString;
std::string durationString;
unsigned startName;
unsigned destName;
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
//compute distance/duration for route summary
intToString(round(distance), lengthString);
int travelTime = time/10 + 1;
intToString(travelTime, durationString);
}
} summary;
double entireLength;
//I know, declaring this public is considered bad. I'm lazy
std::vector <SegmentInformation> pathDescription;
DescriptionFactory();
virtual ~DescriptionFactory();
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
void AppendEncodedPolylineString(std::string &output);
void AppendUnencodedPolylineString(std::string &output);
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & startPhantom);
void SetEndSegment(const PhantomNode & startPhantom);
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
};
#endif /* DESCRIPTIONFACTORY_H_ */
-66
View File
@@ -1,66 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef GPX_DESCRIPTOR_H_
#define GPX_DESCRIPTOR_H_
#include "BaseDescriptor.h"
#include <boost/foreach.hpp>
class GPXDescriptor : public BaseDescriptor{
private:
_DescriptorConfig config;
FixedPointCoordinate current;
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
"\">";
reply.content += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
reply.content += "<rte>";
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
convertInternalLatLonToString(current.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(current.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
reply.content += "</rte></gpx>";
}
};
#endif /* GPX_DESCRIPTOR_H_ */
-397
View File
@@ -1,397 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/Azimuth.h"
#include "../Util/StringUtil.h"
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <algorithm>
class JSONDescriptor : public BaseDescriptor{
private:
_DescriptorConfig config;
DescriptionFactory descriptionFactory;
DescriptionFactory alternateDescriptionFactory;
FixedPointCoordinate current;
unsigned numberOfEnteredRestrictedAreas;
struct RoundAbout{
RoundAbout() :
startIndex(INT_MAX),
nameID(INT_MAX),
leaveAtExit(INT_MAX)
{}
int startIndex;
int nameID;
int leaveAtExit;
} roundAbout;
struct Segment {
Segment() : nameID(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
int nameID;
int length;
int position;
};
std::vector<Segment> shortestSegments, alternativeSegments;
struct RouteNames {
std::string shortestPathName1;
std::string shortestPathName2;
std::string alternativePathName1;
std::string alternativePathName2;
};
public:
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
WriteHeaderToOutput(reply.content);
if(rawRoute.lengthOfShortestPath != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
reply.content += "0,"
"\"status_message\": \"Found route between points\",";
//Get all the coordinates for the computed route
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData );
}
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
} else {
//We do not need to do much, if there is no route ;-)
reply.content += "207,"
"\"status_message\": \"Cannot find route between points\",";
}
descriptionFactory.Run(sEngine, config.z);
reply.content += "\"route_geometry\": ";
if(config.geometry) {
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
} else {
reply.content += "[]";
}
reply.content += ","
"\"route_instructions\": [";
numberOfEnteredRestrictedAreas = 0;
if(config.instructions) {
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
} else {
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
}
}
reply.content += "],";
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
reply.content += "\"route_summary\":";
reply.content += "{";
reply.content += "\"total_distance\":";
reply.content += descriptionFactory.summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += descriptionFactory.summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += "\","
"\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += "\"";
reply.content += "}";
reply.content +=",";
//only one alternative route is computed at this time, so this is hardcoded
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
//Get all the coordinates for the computed route
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
alternateDescriptionFactory.AppendSegment(current, pathData );
}
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
}
alternateDescriptionFactory.Run(sEngine, config.z);
//give an array of alternative routes
reply.content += "\"alternative_geometries\": [";
if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
//Generate the linestrings for each alternative
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
}
reply.content += "],";
reply.content += "\"alternative_instructions\":[";
numberOfEnteredRestrictedAreas = 0;
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
reply.content += "[";
//Generate instructions for each alternative
if(config.instructions) {
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
} else {
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
}
}
reply.content += "]";
}
reply.content += "],";
reply.content += "\"alternative_summaries\":[";
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
//Generate route summary (length, duration) for each alternative
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
reply.content += "{";
reply.content += "\"total_distance\":";
reply.content += alternateDescriptionFactory.summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += alternateDescriptionFactory.summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += "\","
"\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += "\"";
reply.content += "}";
}
reply.content += "],";
//Get Names for both routes
RouteNames routeNames;
GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
reply.content += "\"route_name\":[\"";
reply.content += routeNames.shortestPathName1;
reply.content += "\",\"";
reply.content += routeNames.shortestPathName2;
reply.content += "\"],"
"\"alternative_names\":[";
reply.content += "[\"";
reply.content += routeNames.alternativePathName1;
reply.content += "\",\"";
reply.content += routeNames.alternativePathName2;
reply.content += "\"]";
reply.content += "],";
//list all viapoints so that the client may display it
reply.content += "\"via_points\":[";
std::string tmp;
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
reply.content += "[";
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
reply.content += tmp;
reply.content += "],";
}
reply.content += "[";
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
reply.content += tmp;
reply.content += "]";
}
reply.content += "],";
reply.content += "\"hint_data\": {";
reply.content += "\"checksum\":";
intToString(rawRoute.checkSum, tmp);
reply.content += tmp;
reply.content += ", \"locations\": [";
std::string hint;
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
reply.content += "\"";
EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
reply.content += hint;
reply.content += "\", ";
}
EncodeObjectToBase64(rawRoute.segmentEndCoordinates.back().targetPhantom, hint);
reply.content += "\"";
reply.content += hint;
reply.content += "\"]";
reply.content += "},";
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
reply.content += "}";
}
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
/*** extract names for both alternatives ***/
Segment shortestSegment1, shortestSegment2;
Segment alternativeSegment1, alternativeSegment2;
if(0 < shortestSegments.size()) {
sort(shortestSegments.begin(), shortestSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
shortestSegment1 = shortestSegments[0];
if(0 < alternativeSegments.size()) {
sort(alternativeSegments.begin(), alternativeSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
alternativeSegment1 = alternativeSegments[0];
}
std::vector<Segment> shortestDifference(shortestSegments.size());
std::vector<Segment> alternativeDifference(alternativeSegments.size());
std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
int size_of_difference = shortestDifference.size();
if(0 < size_of_difference ) {
int i = 0;
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
++i;
}
if(i < size_of_difference ) {
shortestSegment2 = shortestDifference[i];
}
}
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
size_of_difference = alternativeDifference.size();
if(0 < size_of_difference ) {
int i = 0;
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
++i;
}
if(i < size_of_difference ) {
alternativeSegment2 = alternativeDifference[i];
}
}
if(shortestSegment1.position > shortestSegment2.position)
std::swap(shortestSegment1, shortestSegment2);
if(alternativeSegment1.position > alternativeSegment2.position)
std::swap(alternativeSegment1, alternativeSegment2);
routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
}
}
inline void WriteHeaderToOutput(std::string & output) {
output += "{"
"\"version\": 0.3,"
"\"status\":";
}
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
//Segment information has following format:
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0;
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments){
reply.content += ",";
}
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
reply.content += tmpInstruction;
reply.content += "-";
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
reply.content += tmpInstruction;
roundAbout.leaveAtExit = 0;
} else {
intToString(currentInstruction, tmpInstruction);
reply.content += tmpInstruction;
}
reply.content += "\",\"";
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
reply.content += "\",";
intToString(segment.length, tmpDist);
reply.content += tmpDist;
reply.content += ",";
intToString(prefixSumOfNecessarySegments, tmpLength);
reply.content += tmpLength;
reply.content += ",";
intToString(segment.duration/10, tmpDuration);
reply.content += tmpDuration;
reply.content += ",\"";
intToString(segment.length, tmpLength);
reply.content += tmpLength;
reply.content += "m\",\"";
reply.content += Azimuth::Get(segment.bearing);
reply.content += "\",";
intToString(round(segment.bearing), tmpBearing);
reply.content += tmpBearing;
reply.content += "]";
segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() ));
}
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
}
if(INT_MAX != lengthOfRoute) {
reply.content += ",[\"";
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
reply.content += tmpInstruction;
reply.content += "\",\"";
reply.content += "\",";
reply.content += "0";
reply.content += ",";
intToString(prefixSumOfNecessarySegments-1, tmpLength);
reply.content += tmpLength;
reply.content += ",";
reply.content += "0";
reply.content += ",\"";
reply.content += "\",\"";
reply.content += Azimuth::Get(0.0);
reply.content += "\",";
reply.content += "0.0";
reply.content += "]";
}
}
};
#endif /* JSON_DESCRIPTOR_H_ */
-3
View File
@@ -1,3 +0,0 @@
The javascript based web client is a seperate project available at
https://github.com/DennisSchiefer/Project-OSRM-Web
-100
View File
@@ -1,100 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "BaseParser.h"
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
luaState = se.getLuaStateForThreadID(0);
ReadUseRestrictionsSetting();
ReadRestrictionExceptions();
}
void BaseParser::ReadUseRestrictionsSetting() {
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
throw OSRMException(
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
);
}
if( lua_isboolean( luaState, -1) ) {
use_turn_restrictions = lua_toboolean(luaState, -1);
}
if( use_turn_restrictions ) {
SimpleLogger().Write() << "Using turn restrictions";
} else {
SimpleLogger().Write() << "Ignoring turn restrictions";
}
}
void BaseParser::ReadRestrictionExceptions() {
if(lua_function_exists(luaState, "get_exceptions" )) {
//get list of turn restriction exceptions
luabind::call_function<void>(
luaState,
"get_exceptions",
boost::ref(restriction_exceptions)
);
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
SimpleLogger().Write() << " " << str;
}
} else {
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
}
}
void BaseParser::report_errors(lua_State *L, const int status) const {
if( 0!=status ) {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
}
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
if(2 > w.path.size()) {
return;
}
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
}
bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const {
//should this restriction be ignored? yes if there's an overlap between:
//a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle
//b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle]
if( "" == except_tag_string ) {
return false;
}
//Be warned, this is quadratic work here, but we assume that
//only a few exceptions are actually defined.
std::vector<std::string> exceptions;
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
BOOST_FOREACH(std::string& str, exceptions) {
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
return true;
}
}
return false;
}
-61
View File
@@ -1,61 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASEPARSER_H_
#define BASEPARSER_H_
#include "ExtractorCallbacks.h"
#include "ScriptingEnvironment.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <boost/noncopyable.hpp>
class BaseParser : boost::noncopyable {
public:
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
virtual ~BaseParser() {}
virtual bool ReadHeader() = 0;
virtual bool Parse() = 0;
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
virtual void report_errors(lua_State *L, const int status) const;
protected:
virtual void ReadUseRestrictionsSetting();
virtual void ReadRestrictionExceptions();
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
ExtractorCallbacks* extractor_callbacks;
ScriptingEnvironment& scriptingEnvironment;
lua_State* luaState;
std::vector<std::string> restriction_exceptions;
bool use_turn_restrictions;
};
#endif /* BASEPARSER_H_ */
-308
View File
@@ -1,308 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "ExtractionContainers.h"
void ExtractionContainers::PrepareData(const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM) {
try {
unsigned usedNodeCounter = 0;
unsigned usedEdgeCounter = 0;
double time = get_timestamp();
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting used ways ... " << std::flush;
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->fromWay){
++wayStartAndEndEdgeIT;
continue;
}
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
++restrictionsIT;
continue;
}
assert(wayStartAndEndEdgeIT->wayID == restrictionsIT->fromWay);
NodeID viaNode = restrictionsIT->restriction.viaNode;
if(wayStartAndEndEdgeIT->firstStart == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstTarget;
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstStart;
} else if(wayStartAndEndEdgeIT->lastStart == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastTarget;
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastStart;
}
++restrictionsIT;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
unsigned usableRestrictionsCounter(0);
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
restrictionsIT = restrictionsVector.begin();
wayStartAndEndEdgeIT = wayStartEndVector.begin();
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
++wayStartAndEndEdgeIT;
continue;
}
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
++restrictionsIT;
continue;
}
NodeID viaNode = restrictionsIT->restriction.viaNode;
if(wayStartAndEndEdgeIT->lastStart == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastTarget;
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastStart;
} else if(wayStartAndEndEdgeIT->firstStart == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstTarget;
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstStart;
}
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
++usableRestrictionsCounter;
}
++restrictionsIT;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
//serialize restrictions
std::ofstream restrictionsOutstream;
restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
restrictionsOutstream.write((char*)&uuid, sizeof(UUID));
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(TurnRestriction));
}
}
restrictionsOutstream.close();
std::ofstream fout;
fout.open(output_file_name.c_str(), std::ios::binary);
fout.write((char*)&uuid, sizeof(UUID));
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
time = get_timestamp();
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
STXXLNodeVector::iterator nodesIT = allNodes.begin();
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
if(*usedNodeIDsIT < nodesIT->id){
++usedNodeIDsIT;
continue;
}
if(*usedNodeIDsIT > nodesIT->id) {
++nodesIT;
continue;
}
if(*usedNodeIDsIT == nodesIT->id) {
fout.write((char*)&(*nodesIT), sizeof(_Node));
++usedNodeCounter;
++usedNodeIDsIT;
++nodesIT;
}
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] setting number of nodes ... " << std::flush;
std::ios::pos_type positionInFile = fout.tellp();
fout.seekp(std::ios::beg+sizeof(UUID));
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
fout.seekp(positionInFile);
std::cout << "ok" << std::endl;
time = get_timestamp();
// Sort edges by start.
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Setting start coords ... " << std::flush;
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
// Traverse list of edges and nodes in parallel and set start coord
nodesIT = allNodes.begin();
STXXLEdgeVector::iterator edgeIT = allEdges.begin();
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
if(edgeIT->start < nodesIT->id){
++edgeIT;
continue;
}
if(edgeIT->start > nodesIT->id) {
nodesIT++;
continue;
}
if(edgeIT->start == nodesIT->id) {
edgeIT->startCoord.lat = nodesIT->lat;
edgeIT->startCoord.lon = nodesIT->lon;
++edgeIT;
}
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
// Sort Edges by target
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Setting target coords ... " << std::flush;
// Traverse list of edges and nodes in parallel and set target coord
nodesIT = allNodes.begin();
edgeIT = allEdges.begin();
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
if(edgeIT->target < nodesIT->id){
++edgeIT;
continue;
}
if(edgeIT->target > nodesIT->id) {
++nodesIT;
continue;
}
if(edgeIT->target == nodesIT->id) {
if(edgeIT->startCoord.lat != INT_MIN && edgeIT->startCoord.lon != INT_MIN) {
edgeIT->targetCoord.lat = nodesIT->lat;
edgeIT->targetCoord.lon = nodesIT->lon;
double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
assert(edgeIT->speed != -1);
double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
int intWeight = std::max(1, (int)std::floor((edgeIT->isDurationSet ? edgeIT->speed : weight)+.5) );
int intDist = std::max(1, (int)distance);
short zero = 0;
short one = 1;
fout.write((char*)&edgeIT->start, sizeof(unsigned));
fout.write((char*)&edgeIT->target, sizeof(unsigned));
fout.write((char*)&intDist, sizeof(int));
switch(edgeIT->direction) {
case ExtractionWay::notSure:
fout.write((char*)&zero, sizeof(short));
break;
case ExtractionWay::oneway:
fout.write((char*)&one, sizeof(short));
break;
case ExtractionWay::bidirectional:
fout.write((char*)&zero, sizeof(short));
break;
case ExtractionWay::opposite:
fout.write((char*)&one, sizeof(short));
break;
default:
std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
assert(false);
break;
}
fout.write((char*)&intWeight, sizeof(int));
assert(edgeIT->type >= 0);
fout.write((char*)&edgeIT->type, sizeof(short));
fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
++usedEdgeCounter;
}
++edgeIT;
}
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] setting number of edges ... " << std::flush;
fout.seekp(positionInFile);
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
fout.close();
std::cout << "ok" << std::endl;
time = get_timestamp();
std::cout << "[extractor] writing street name index ... " << std::flush;
std::string nameOutFileName = (output_file_name + ".names");
std::ofstream nameOutFile(nameOutFileName.c_str(), std::ios::binary);
unsigned sizeOfNameIndex = nameVector.size();
nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
BOOST_FOREACH(const std::string & str, nameVector) {
unsigned lengthOfRawString = strlen(str.c_str());
nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
nameOutFile.write(str.c_str(), lengthOfRawString);
}
nameOutFile.close();
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
// time = get_timestamp();
// cout << "[extractor] writing address list ... " << flush;
//
// adressFileName.append(".address");
// ofstream addressOutFile(adressFileName.c_str());
// for(STXXLAddressVector::iterator it = adressVector.begin(); it != adressVector.end(); it++) {
// addressOutFile << it->node.id << "|" << it->node.lat << "|" << it->node.lon << "|" << it->city << "|" << it->street << "|" << it->housenumber << "|" << it->state << "|" << it->country << "\n";
// }
// addressOutFile.close();
// cout << "ok, after " << get_timestamp() - time << "s" << endl;
SimpleLogger().Write() << "Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges";
} catch ( const std::exception& e ) {
std::cerr << "Caught Execption:" << e.what() << std::endl;
}
}
-67
View File
@@ -1,67 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTIONCONTAINERS_H_
#define EXTRACTIONCONTAINERS_H_
#include "ExtractorStructs.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
#include "../Util/UUID.h"
#include <boost/foreach.hpp>
#include <stxxl.h>
class ExtractionContainers {
public:
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<_Node> STXXLNodeVector;
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
typedef stxxl::vector<std::string> STXXLStringVector;
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
ExtractionContainers() {
//Check if another instance of stxxl is already running or if there is a general problem
stxxl::vector<unsigned> testForRunningInstance;
nameVector.push_back("");
}
virtual ~ExtractionContainers() {
usedNodeIDs.clear();
allNodes.clear();
allEdges.clear();
nameVector.clear();
restrictionsVector.clear();
wayStartEndVector.clear();
}
void PrepareData( const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM);
STXXLNodeIDVector usedNodeIDs;
STXXLNodeVector allNodes;
STXXLEdgeVector allEdges;
STXXLStringVector nameVector;
STXXLRestrictionsVector restrictionsVector;
STXXLWayIDStartEndVector wayStartEndVector;
const UUID uuid;
};
#endif /* EXTRACTIONCONTAINERS_H_ */
-80
View File
@@ -1,80 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
#define EXTRACTIONHELPERFUNCTIONS_H_
#include "../Util/StringUtil.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <boost/regex.hpp>
#include <climits>
namespace qi = boost::spirit::qi;
//TODO: Move into LUA
inline bool durationIsValid(const std::string &s) {
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
std::vector< std::string > result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
bool matched = regex_match(s, e);
return matched;
}
inline unsigned parseDuration(const std::string &s) {
unsigned hours = 0;
unsigned minutes = 0;
unsigned seconds = 0;
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
std::vector< std::string > result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
bool matched = regex_match(s, e);
if(matched) {
if(1 == result.size()) {
minutes = stringToInt(result[0]);
}
if(2 == result.size()) {
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
if(3 == result.size()) {
seconds = stringToInt(result[2]);
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
return 10*(3600*hours+60*minutes+seconds);
}
return UINT_MAX;
}
inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
boost::algorithm::to_lower(input);
int n = stringToInt(input);
if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
n = (n*1609)/1000;
}
return n;
}
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
-124
View File
@@ -1,124 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "ExtractorCallbacks.h"
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
externalMemory = ext;
stringMap = strMap;
}
ExtractorCallbacks::~ExtractorCallbacks() { }
/** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::nodeFunction(const _Node &n) {
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
externalMemory->allNodes.push_back(n);
}
}
bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
externalMemory->restrictionsVector.push_back(r);
return true;
}
/** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
if(UINT_MAX == parsed_way.id){
SimpleLogger().Write(logDEBUG) <<
"found bogus way with id: " << parsed_way.id <<
" of size " << parsed_way.path.size();
return;
}
if(0 < parsed_way.duration) {
//TODO: iterate all way segments and set duration corresponding to the length of each segment
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
}
if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){
SimpleLogger().Write(logDEBUG) <<
"found way with bogus speed, id: " << parsed_way.id;
return;
}
//Get the unique identifier for the street name
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
if(stringMap->end() == string_map_iterator) {
parsed_way.nameID = externalMemory->nameVector.size();
externalMemory->nameVector.push_back(parsed_way.name);
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
} else {
parsed_way.nameID = string_map_iterator->second;
}
if(ExtractionWay::opposite == parsed_way.direction) {
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
parsed_way.direction = ExtractionWay::oneway;
}
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->allEdges.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
parsed_way.speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted
)
);
externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
}
externalMemory->usedNodeIDs.push_back(parsed_way.path.back());
//The following information is needed to identify start and end segments of restrictions
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
if(split_bidirectional_edge) { //Only true if the way should be split
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->allEdges.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction)
)
);
}
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
}
}
}
-60
View File
@@ -1,60 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTORCALLBACKS_H_
#define EXTRACTORCALLBACKS_H_
#include "ExtractionContainers.h"
#include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h"
#include "../DataStructures/Coordinate.h"
#include <cfloat>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <string>
#include <vector>
class ExtractorCallbacks{
private:
StringMap * stringMap;
ExtractionContainers * externalMemory;
ExtractorCallbacks();
public:
explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
~ExtractorCallbacks();
/** warning: caller needs to take care of synchronization! */
void nodeFunction(const _Node &n);
bool restrictionFunction(const _RawRestrictionContainer &r);
/** warning: caller needs to take care of synchronization! */
void wayFunction(ExtractionWay &w);
};
#endif /* EXTRACTORCALLBACKS_H_ */
-221
View File
@@ -1,221 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTORSTRUCTS_H_
#define EXTRACTORSTRUCTS_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Restriction.h"
#include "../typedefs.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <boost/unordered_map.hpp>
#include <climits>
#include <string>
typedef boost::unordered_map<std::string, NodeID > StringMap;
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
struct ExtractionWay {
ExtractionWay() {
Clear();
}
inline void Clear(){
id = UINT_MAX;
nameID = UINT_MAX;
path.clear();
keyVals.clear();
direction = ExtractionWay::notSure;
speed = -1;
backward_speed = -1;
duration = -1;
type = -1;
access = true;
roundabout = false;
isAccessRestricted = false;
ignoreInGrid = false;
}
enum Directions {
notSure = 0, oneway, bidirectional, opposite
};
Directions direction;
unsigned id;
unsigned nameID;
std::string name;
double speed;
double backward_speed;
double duration;
short type;
bool access;
bool roundabout;
bool isAccessRestricted;
bool ignoreInGrid;
std::vector< NodeID > path;
HashTable<std::string, std::string> keyVals;
};
struct ExtractorRelation {
ExtractorRelation() : type(unknown){}
enum {
unknown = 0, ferry, turnRestriction
} type;
HashTable<std::string, std::string> keyVals;
};
struct InternalExtractorEdge {
InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {};
InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) {
assert(0 <= type);
}
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) {
assert(0 <= type);
}
NodeID start;
NodeID target;
short type;
short direction;
double speed;
unsigned nameID;
bool isRoundabout;
bool ignoreInGrid;
bool isDurationSet;
bool isAccessRestricted;
bool isContraFlow;
FixedPointCoordinate startCoord;
FixedPointCoordinate targetCoord;
static InternalExtractorEdge min_value() {
return InternalExtractorEdge(0,0);
}
static InternalExtractorEdge max_value() {
return InternalExtractorEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
}
};
struct _WayIDStartAndEndEdge {
unsigned wayID;
NodeID firstStart;
NodeID firstTarget;
NodeID lastStart;
NodeID lastTarget;
_WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {}
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
static _WayIDStartAndEndEdge min_value() {
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
}
static _WayIDStartAndEndEdge max_value() {
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
}
};
struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
typedef _WayIDStartAndEndEdge value_type;
bool operator () (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
return a.wayID < b.wayID;
}
value_type max_value() {
return _WayIDStartAndEndEdge::max_value();
}
value_type min_value() {
return _WayIDStartAndEndEdge::min_value();
}
};
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
typedef NodeID value_type;
bool operator () (const NodeID & a, const NodeID & b) const {
return a < b;
}
value_type max_value() {
return 0xffffffff;
}
value_type min_value() {
return 0x0;
}
};
struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
typedef _Node value_type;
bool operator () (const _Node & a, const _Node & b) const {
return a.id < b.id;
}
value_type max_value() {
return _Node::max_value();
}
value_type min_value() {
return _Node::min_value();
}
};
struct CmpEdgeByStartID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
typedef InternalExtractorEdge value_type;
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
return a.start < b.start;
}
value_type max_value() {
return InternalExtractorEdge::max_value();
}
value_type min_value() {
return InternalExtractorEdge::min_value();
}
};
struct CmpEdgeByTargetID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
typedef InternalExtractorEdge value_type;
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
return a.target < b.target;
}
value_type max_value() {
return InternalExtractorEdge::max_value();
}
value_type min_value() {
return InternalExtractorEdge::min_value();
}
};
inline std::string GetRandomString() {
char s[128];
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < 127; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[127] = 0;
return std::string(s);
}
#endif /* EXTRACTORSTRUCTS_H_ */
-487
View File
@@ -1,487 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "PBFParser.h"
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
input.open(fileName, std::ios::in | std::ios::binary);
if (!input) {
throw OSRMException("pbf file not found.");
}
#ifndef NDEBUG
blockCount = 0;
groupCount = 0;
#endif
}
PBFParser::~PBFParser() {
if(input.is_open()) {
input.close();
}
// Clean up any leftover ThreadData objects in the queue
_ThreadData* td;
while (threadDataQueue->try_pop(td)) {
delete td;
}
google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG
SimpleLogger().Write(logDEBUG) <<
"parsed " << blockCount <<
" blocks from pbf with " << groupCount <<
" groups";
#endif
}
inline bool PBFParser::ReadHeader() {
_ThreadData initData;
/** read Header */
if(!readPBFBlobHeader(input, &initData)) {
return false;
}
if(readBlob(input, &initData)) {
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
std::cerr << "[error] Header not parseable!" << std::endl;
return false;
}
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
bool supported = false;
if ( "OsmSchema-V0.6" == feature ) {
supported = true;
}
else if ( "DenseNodes" == feature ) {
supported = true;
}
if ( !supported ) {
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
return false;
}
}
} else {
std::cerr << "[error] blob not loaded!" << std::endl;
}
return true;
}
inline void PBFParser::ReadData() {
bool keepRunning = true;
do {
_ThreadData *threadData = new _ThreadData();
keepRunning = readNextBlock(input, threadData);
if (keepRunning) {
threadDataQueue->push(threadData);
} else {
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
delete threadData;
}
} while(keepRunning);
}
inline void PBFParser::ParseData() {
while (true) {
_ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData);
if( NULL==threadData ) {
SimpleLogger().Write() << "Parse Data Thread Finished";
threadDataQueue->push(NULL); // Signal end of data for other threads
break;
}
loadBlock(threadData);
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
threadData->currentGroupID = i;
loadGroup(threadData);
if(threadData->entityTypeIndicator == TypeNode) {
parseNode(threadData);
}
if(threadData->entityTypeIndicator == TypeWay) {
parseWay(threadData);
}
if(threadData->entityTypeIndicator == TypeRelation) {
parseRelation(threadData);
}
if(threadData->entityTypeIndicator == TypeDenseNode) {
parseDenseNode(threadData);
}
}
delete threadData;
threadData = NULL;
}
}
inline bool PBFParser::Parse() {
// Start the read and parse threads
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
//Open several parse threads that are synchronized before call to
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
// Wait for the threads to finish
readThread.join();
parseThread.join();
return true;
}
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
int denseTagIndex = 0;
int64_t m_lastDenseID = 0;
int64_t m_lastDenseLatitude = 0;
int64_t m_lastDenseLongitude = 0;
const int number_of_nodes = dense.id_size();
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
for(int i = 0; i < number_of_nodes; ++i) {
m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i );
extracted_nodes_vector[i].id = m_lastDenseID;
extracted_nodes_vector[i].lat = COORDINATE_PRECISION*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
extracted_nodes_vector[i].lon = COORDINATE_PRECISION*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
while (denseTagIndex < dense.keys_vals_size()) {
const int tagValue = dense.keys_vals( denseTagIndex );
if( 0==tagValue ) {
++denseTagIndex;
break;
}
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
extracted_nodes_vector[i].keyVals.insert(std::make_pair(key, value));
denseTagIndex += 2;
}
}
#pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_nodes; ++i) {
ImportNode &n = extracted_nodes_vector[i];
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
}
BOOST_FOREACH(ImportNode &n, extracted_nodes_vector) {
extractor_callbacks->nodeFunction(n);
}
}
inline void PBFParser::parseNode(_ThreadData * ) {
throw OSRMException(
"Parsing of simple nodes not supported. PBF should use dense nodes"
);
}
inline void PBFParser::parseRelation(_ThreadData * threadData) {
//TODO: leave early, if relation is not a restriction
//TODO: reuse rawRestriction container
if( !use_turn_restrictions ) {
return;
}
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
for(int i = 0; i < group.relations_size(); ++i ) {
std::string except_tag_string;
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
bool isRestriction = false;
bool isOnlyRestriction = false;
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
if ("type" == key) {
if( "restriction" == val) {
isRestriction = true;
} else {
break;
}
}
if ("restriction" == key) {
if(val.find("only_") == 0) {
isOnlyRestriction = true;
}
}
if ("except" == key) {
except_tag_string = val;
}
}
if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
continue;
}
if(isRestriction) {
int64_t lastRef = 0;
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
lastRef += inputRelation.memids(rolesIndex);
if(!("from" == role || "to" == role || "via" == role)) {
continue;
}
switch(inputRelation.types(rolesIndex)) {
case 0: //node
if("from" == role || "to" == role) { //Only via should be a node
continue;
}
assert("via" == role);
if(UINT_MAX != currentRestrictionContainer.viaNode) {
currentRestrictionContainer.viaNode = UINT_MAX;
}
assert(UINT_MAX == currentRestrictionContainer.viaNode);
currentRestrictionContainer.restriction.viaNode = lastRef;
break;
case 1: //way
assert("from" == role || "to" == role || "via" == role);
if("from" == role) {
currentRestrictionContainer.fromWay = lastRef;
}
if ("to" == role) {
currentRestrictionContainer.toWay = lastRef;
}
if ("via" == role) {
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
currentRestrictionContainer.viaNode = lastRef;
}
break;
case 2: //relation, not used. relations relating to relations are evil.
continue;
assert(false);
break;
default: //should not happen
//cout << "unknown";
assert(false);
break;
}
}
if(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) {
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
}
}
inline void PBFParser::parseWay(_ThreadData * threadData) {
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
for(int i = 0; i < number_of_ways; ++i) {
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
parsed_way_vector[i].id = inputWay.id();
unsigned pathNode(0);
const int number_of_referenced_nodes = inputWay.refs_size();
for(int j = 0; j < number_of_referenced_nodes; ++j) {
pathNode += inputWay.refs(j);
parsed_way_vector[i].path.push_back(pathNode);
}
assert(inputWay.keys_size() == inputWay.vals_size());
const int number_of_keys = inputWay.keys_size();
for(int j = 0; j < number_of_keys; ++j) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
parsed_way_vector[i].keyVals.insert(std::make_pair(key, val));
}
}
#pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_ways; ++i) {
ExtractionWay & w = parsed_way_vector[i];
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
}
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
extractor_callbacks->wayFunction(w);
}
}
inline void PBFParser::loadGroup(_ThreadData * threadData) {
#ifndef NDEBUG
++groupCount;
#endif
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
threadData->entityTypeIndicator = 0;
if ( group.nodes_size() != 0 ) {
threadData->entityTypeIndicator = TypeNode;
}
if ( group.ways_size() != 0 ) {
threadData->entityTypeIndicator = TypeWay;
}
if ( group.relations_size() != 0 ) {
threadData->entityTypeIndicator = TypeRelation;
}
if ( group.has_dense() ) {
threadData->entityTypeIndicator = TypeDenseNode;
assert( group.dense().id_size() != 0 );
}
assert( threadData->entityTypeIndicator != 0 );
}
inline void PBFParser::loadBlock(_ThreadData * threadData) {
#ifndef NDEBUG
++blockCount;
#endif
threadData->currentGroupID = 0;
threadData->currentEntityID = 0;
}
inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
int size(0);
stream.read((char *)&size, sizeof(int));
size = swapEndian(size);
if(stream.eof()) {
return false;
}
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
return false;
}
char *data = new char[size];
stream.read(data, size*sizeof(data[0]));
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
delete[] data;
return dataSuccessfullyParsed;
}
inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
unsigned rawSize = threadData->PBFBlob.raw_size();
char* unpackedDataArray = new char[rawSize];
z_stream compressedDataStream;
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
compressedDataStream.avail_out = rawSize;
compressedDataStream.zalloc = Z_NULL;
compressedDataStream.zfree = Z_NULL;
compressedDataStream.opaque = Z_NULL;
int ret = inflateInit( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to init zlib stream" << std::endl;
delete[] unpackedDataArray;
return false;
}
ret = inflate( &compressedDataStream, Z_FINISH );
if ( ret != Z_STREAM_END ) {
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
std::cerr << "[error] Error type: " << ret << std::endl;
delete[] unpackedDataArray;
return false;
}
ret = inflateEnd( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
delete[] unpackedDataArray;
return false;
}
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
delete[] unpackedDataArray;
return true;
}
inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
return false;
}
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
const int size = threadData->PBFBlobHeader.datasize();
if ( size < 0 || size > MAX_BLOB_SIZE ) {
std::cerr << "[error] invalid Blob size:" << size << std::endl;
return false;
}
char* data = new char[size];
stream.read(data, sizeof(data[0])*size);
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
std::cerr << "[error] failed to parse blob" << std::endl;
delete[] data;
return false;
}
if ( threadData->PBFBlob.has_raw() ) {
const std::string& data = threadData->PBFBlob.raw();
threadData->charBuffer.clear();
threadData->charBuffer.resize( data.size() );
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
} else if ( threadData->PBFBlob.has_zlib_data() ) {
if ( !unpackZLIB(stream, threadData) ) {
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
delete[] data;
return false;
}
} else if ( threadData->PBFBlob.has_lzma_data() ) {
if ( !unpackLZMA(stream, threadData) ) {
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
}
delete[] data;
return false;
} else {
std::cerr << "[error] Blob contains no data" << std::endl;
delete[] data;
return false;
}
delete[] data;
return true;
}
bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
if ( !readPBFBlobHeader(stream, threadData) ){
return false;
}
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
return false;
}
if ( !readBlob(stream, threadData) ) {
return false;
}
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
return false;
}
return true;
}
-104
View File
@@ -1,104 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PBFPARSER_H_
#define PBFPARSER_H_
#include "BaseParser.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ConcurrentQueue.h"
#include "../Util/MachineInfo.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
#include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h>
#include <zlib.h>
class PBFParser : public BaseParser {
enum EntityType {
TypeNode = 1,
TypeWay = 2,
TypeRelation = 4,
TypeDenseNode = 8
} ;
struct _ThreadData {
int currentGroupID;
int currentEntityID;
short entityTypeIndicator;
OSMPBF::BlobHeader PBFBlobHeader;
OSMPBF::Blob PBFBlob;
OSMPBF::HeaderBlock PBFHeaderBlock;
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
std::vector<char> charBuffer;
};
public:
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
virtual ~PBFParser();
inline bool ReadHeader();
inline bool Parse();
private:
inline void ReadData();
inline void ParseData();
inline void parseDenseNode(_ThreadData * threadData);
inline void parseNode(_ThreadData * );
inline void parseRelation(_ThreadData * threadData);
inline void parseWay(_ThreadData * threadData);
inline void loadGroup(_ThreadData * threadData);
inline void loadBlock(_ThreadData * threadData);
inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData);
inline bool unpackZLIB(std::fstream &, _ThreadData * threadData);
inline bool unpackLZMA(std::fstream &, _ThreadData * );
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ;
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData);
static const int NANO = 1000 * 1000 * 1000;
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
#ifndef NDEBUG
/* counting the number of read blocks and groups */
unsigned groupCount;
unsigned blockCount;
#endif
std::fstream input; // the input stream to parse
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
};
#endif /* PBFPARSER_H_ */
-109
View File
@@ -1,109 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "ScriptingEnvironment.h"
ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
SimpleLogger().Write() << "Using script " << fileName;
// Create a new lua state
for(int i = 0; i < omp_get_max_threads(); ++i) {
luaStateVector.push_back(luaL_newstate());
}
// Connect LuaBind to this lua state for all threads
#pragma omp parallel
{
lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num());
luabind::open(myLuaState);
//open utility libraries string library;
luaL_openlibs(myLuaState);
luaAddScriptFolderToLoadPath( myLuaState, fileName );
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>),
luabind::def("parseMaxspeed", parseMaxspeed),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
luabind::module(myLuaState) [
luabind::class_<HashTable<std::string, std::string> >("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)
];
luabind::module(myLuaState) [
luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readwrite("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)
];
luabind::module(myLuaState) [
luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants") [
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]
];
luabind::module(myLuaState) [
luabind::class_<std::vector<std::string> >("vector")
.def("Add", &std::vector<std::string>::push_back)
];
if(0 != luaL_dofile(myLuaState, fileName) ) {
throw OSRMException("ERROR occured in scripting block");
}
}
}
ScriptingEnvironment::~ScriptingEnvironment() {
for(unsigned i = 0; i < luaStateVector.size(); ++i) {
// luaStateVector[i];
}
}
lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
return luaStateVector[id];
}
-46
View File
@@ -1,46 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SCRIPTINGENVIRONMENT_H_
#define SCRIPTINGENVIRONMENT_H_
#include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <vector>
class ScriptingEnvironment {
public:
ScriptingEnvironment();
ScriptingEnvironment(const char * fileName);
virtual ~ScriptingEnvironment();
lua_State * getLuaStateForThreadID(const int);
std::vector<lua_State *> luaStateVector;
};
#endif /* SCRIPTINGENVIRONMENT_H_ */
-277
View File
@@ -1,277 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "XMLParser.h"
#include "ExtractorStructs.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/InputReaderFactory.h"
#include <boost/ref.hpp>
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
SimpleLogger().Write(logWARNING) <<
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
inputReader = inputReaderFactory(filename);
}
bool XMLParser::ReadHeader() {
return (xmlTextReaderRead( inputReader ) == 1);
}
bool XMLParser::Parse() {
while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int type = xmlTextReaderNodeType( inputReader );
//1 is Element
if ( type != 1 ) {
continue;
}
xmlChar* currentName = xmlTextReaderName( inputReader );
if ( currentName == NULL ) {
continue;
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
ImportNode n = _ReadXMLNode();
ParseNodeInLua( n, luaState );
extractor_callbacks->nodeFunction(n);
// if(!extractor_callbacks->nodeFunction(n))
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
ExtractionWay way = _ReadXMLWay( );
ParseWayInLua( way, luaState );
extractor_callbacks->wayFunction(way);
// if(!extractor_callbacks->wayFunction(way))
// std::cerr << "[PBFParser] way not parsed" << std::endl;
}
if( use_turn_restrictions ) {
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
_RawRestrictionContainer r = _ReadXMLRestriction();
if(r.fromWay != UINT_MAX) {
if(!extractor_callbacks->restrictionFunction(r)) {
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
}
}
}
}
xmlFree( currentName );
}
return true;
}
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
_RawRestrictionContainer restriction;
std::string except_tag_string;
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader );
if ( childType != 1 && childType != 15 ) {
continue;
}
const int childDepth = xmlTextReaderDepth( inputReader );
xmlChar* childName = xmlTextReaderName( inputReader );
if ( childName == NULL ) {
continue;
}
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
xmlFree( childName );
break;
}
if ( childType != 1 ) {
xmlFree( childName );
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
if ( k != NULL && value != NULL ) {
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
if(0 == std::string((const char *) value).find("only_")) {
restriction.restriction.flags.isOnly = true;
}
}
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
except_tag_string = (const char*) value;
}
}
if ( k != NULL ) {
xmlFree( k );
}
if ( value != NULL ) {
xmlFree( value );
}
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) {
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.toWay = stringToUint((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.fromWay = stringToUint((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
restriction.restriction.viaNode = stringToUint((const char*) ref);
}
if(NULL != type) {
xmlFree( type );
}
if(NULL != role) {
xmlFree( role );
}
if(NULL != ref) {
xmlFree( ref );
}
}
}
xmlFree( childName );
}
}
if( ShouldIgnoreRestriction(except_tag_string) ) {
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
}
return restriction;
}
ExtractionWay XMLParser::_ReadXMLWay() {
ExtractionWay way;
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader );
while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader );
if ( childType != 1 && childType != 15 ) {
continue;
}
const int childDepth = xmlTextReaderDepth( inputReader );
xmlChar* childName = xmlTextReaderName( inputReader );
if ( childName == NULL ) {
continue;
}
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
way.id = stringToUint((char*)id);
xmlFree(id);
xmlFree( childName );
break;
}
if ( childType != 1 ) {
xmlFree( childName );
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
// cout << "->k=" << k << ", v=" << value << endl;
if ( k != NULL && value != NULL ) {
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
}
if ( k != NULL ) {
xmlFree( k );
}
if ( value != NULL ) {
xmlFree( value );
}
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) {
way.path.push_back( stringToUint(( const char* ) ref ) );
xmlFree( ref );
}
}
xmlFree( childName );
}
}
return way;
}
ImportNode XMLParser::_ReadXMLNode() {
ImportNode node;
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
if ( attribute != NULL ) {
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
if ( attribute != NULL ) {
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
if ( attribute != NULL ) {
node.id = stringToUint(( const char* ) attribute );
xmlFree( attribute );
}
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader );
while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader );
// 1 = Element, 15 = EndElement
if ( childType != 1 && childType != 15 ) {
continue;
}
const int childDepth = xmlTextReaderDepth( inputReader );
xmlChar* childName = xmlTextReaderName( inputReader );
if ( childName == NULL ) {
continue;
}
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
xmlFree( childName );
break;
}
if ( childType != 1 ) {
xmlFree( childName );
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
if ( k != NULL && value != NULL ) {
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
}
if ( k != NULL ) {
xmlFree( k );
}
if ( value != NULL ) {
xmlFree( value );
}
}
xmlFree( childName );
}
}
return node;
}
-46
View File
@@ -1,46 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef XMLPARSER_H_
#define XMLPARSER_H_
#include "BaseParser.h"
#include "../DataStructures/Coordinate.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <libxml/xmlreader.h>
class XMLParser : public BaseParser {
public:
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
bool ReadHeader();
bool Parse();
private:
_RawRestrictionContainer _ReadXMLRestriction();
ExtractionWay _ReadXMLWay();
ImportNode _ReadXMLNode();
xmlTextReaderPtr inputReader;
};
#endif /* XMLPARSER_H_ */
-7
View File
@@ -1,7 +0,0 @@
source "http://rubygems.org"
gem "cucumber"
gem "rake"
gem "osmlib-base"
gem "sys-proctable"
gem "rspec-expectations"
-30
View File
@@ -1,30 +0,0 @@
GEM
remote: http://rubygems.org/
specs:
builder (3.0.0)
cucumber (1.1.4)
builder (>= 2.1.2)
diff-lcs (>= 1.1.2)
gherkin (~> 2.7.1)
json (>= 1.4.6)
term-ansicolor (>= 1.0.6)
diff-lcs (1.1.3)
gherkin (2.7.6)
json (>= 1.4.6)
json (1.6.5)
osmlib-base (0.1.4)
rake (0.9.2.2)
rspec-expectations (2.11.3)
diff-lcs (~> 1.1.3)
sys-proctable (0.9.1)
term-ansicolor (1.0.7)
PLATFORMS
ruby
DEPENDENCIES
cucumber
osmlib-base
rake
rspec-expectations
sys-proctable
-661
View File
@@ -1,661 +0,0 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.
-122
View File
@@ -1,122 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "OSRM.h"
OSRM::OSRM(const char * server_ini_path) {
if( !testDataFile(server_ini_path) ){
std::string error_message = std::string(server_ini_path) + " not found";
throw OSRMException(error_message.c_str());
}
IniFile serverConfig(server_ini_path);
boost::filesystem::path base_path =
boost::filesystem::absolute(server_ini_path).parent_path();
if ( !serverConfig.Holds("hsgrData")) {
throw OSRMException("no ram index file name in server ini");
}
if ( !serverConfig.Holds("ramIndex") ) {
throw OSRMException("no mem index file name in server ini");
}
if ( !serverConfig.Holds("fileIndex") ) {
throw OSRMException("no nodes file name in server ini");
}
if ( !serverConfig.Holds("nodesData") ) {
throw OSRMException("no nodes file name in server ini");
}
if ( !serverConfig.Holds("edgesData") ) {
throw OSRMException("no edges file name in server ini");
}
boost::filesystem::path hsgr_path = boost::filesystem::absolute(
serverConfig.GetParameter("hsgrData"),
base_path
);
boost::filesystem::path ram_index_path = boost::filesystem::absolute(
serverConfig.GetParameter("ramIndex"),
base_path
);
boost::filesystem::path file_index_path = boost::filesystem::absolute(
serverConfig.GetParameter("fileIndex"),
base_path
);
boost::filesystem::path node_data_path = boost::filesystem::absolute(
serverConfig.GetParameter("nodesData"),
base_path
);
boost::filesystem::path edge_data_path = boost::filesystem::absolute(
serverConfig.GetParameter("edgesData"),
base_path
);
boost::filesystem::path name_data_path = boost::filesystem::absolute(
serverConfig.GetParameter("namesData"),
base_path
);
boost::filesystem::path timestamp_path = boost::filesystem::absolute(
serverConfig.GetParameter("timestamp"),
base_path
);
objects = new QueryObjectsStorage(
hsgr_path.string(),
ram_index_path.string(),
file_index_path.string(),
node_data_path.string(),
edge_data_path.string(),
name_data_path.string(),
timestamp_path.string()
);
RegisterPlugin(new HelloWorldPlugin());
RegisterPlugin(new LocatePlugin(objects));
RegisterPlugin(new NearestPlugin(objects));
RegisterPlugin(new TimestampPlugin(objects));
RegisterPlugin(new ViaRoutePlugin(objects));
}
OSRM::~OSRM() {
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, pluginMap) {
delete plugin_pointer.second;
}
delete objects;
}
void OSRM::RegisterPlugin(BasePlugin * plugin) {
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if( pluginMap.find(plugin->GetDescriptor()) != pluginMap.end() ) {
delete pluginMap[plugin->GetDescriptor()];
}
pluginMap.insert(std::make_pair(plugin->GetDescriptor(), plugin));
}
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
const PluginMap::const_iterator & iter = pluginMap.find(route_parameters.service);
if(pluginMap.end() != iter) {
reply.status = http::Reply::ok;
iter->second->HandleRequest(route_parameters, reply );
} else {
reply = http::Reply::stockReply(http::Reply::badRequest);
}
}
-58
View File
@@ -1,58 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef OSRM_H
#define OSRM_H
#include "OSRM.h"
#include "../Plugins/BasePlugin.h"
#include "../Plugins/HelloWorldPlugin.h"
#include "../Plugins/LocatePlugin.h"
#include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h"
#include "../Server/DataStructures/RouteParameters.h"
#include "../Util/IniFile.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Server/BasicDatastructures.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <vector>
class OSRM : boost::noncopyable {
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
QueryObjectsStorage * objects;
public:
OSRM(const char * server_ini_path);
~OSRM();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
private:
void RegisterPlugin(BasePlugin * plugin);
PluginMap pluginMap;
};
#endif //OSRM_H
-52
View File
@@ -1,52 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASEPLUGIN_H_
#define BASEPLUGIN_H_
#include "../DataStructures/Coordinate.h"
#include "../Server/BasicDatastructures.h"
#include "../Server/DataStructures/RouteParameters.h"
#include <string>
#include <vector>
class BasePlugin {
public:
BasePlugin() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BasePlugin() { }
virtual const std::string & GetDescriptor() const = 0;
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
inline bool checkCoord(const FixedPointCoordinate & c) {
if(
c.lat > 90*COORDINATE_PRECISION ||
c.lat < -90*COORDINATE_PRECISION ||
c.lon > 180*COORDINATE_PRECISION ||
c.lon < -180*COORDINATE_PRECISION
) {
return false;
}
return true;
}
};
#endif /* BASEPLUGIN_H_ */
-63
View File
@@ -1,63 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef HELLOWORLDPLUGIN_H_
#define HELLOWORLDPLUGIN_H_
#include "BasePlugin.h"
#include <sstream>
class HelloWorldPlugin : public BasePlugin {
public:
HelloWorldPlugin() : descriptor_string("hello"){}
virtual ~HelloWorldPlugin() { }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
reply.status = http::Reply::ok;
reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
std::stringstream content;
content << "<pre>";
content << "zoom level: " << routeParameters.zoomLevel << "\n";
content << "checksum: " << routeParameters.checkSum << "\n";
content << "instructions: " << (routeParameters.printInstructions ? "yes" : "no") << "\n";
content << "geometry: " << (routeParameters.geometry ? "yes" : "no") << "\n";
content << "compression: " << (routeParameters.compression ? "yes" : "no") << "\n";
content << "output format: " << routeParameters.outputFormat << "\n";
content << "json parameter: " << routeParameters.jsonpParameter << "\n";
content << "language: " << routeParameters.language << "<br>";
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
content << " [" << i << "] " << routeParameters.coordinates[i].lat/COORDINATE_PRECISION << "," << routeParameters.coordinates[i].lon/COORDINATE_PRECISION << "\n";
}
content << "Number of hints: " << routeParameters.hints.size() << "\n";
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
content << " [" << i << "] " << routeParameters.hints[i] << "\n";
}
content << "</pre>";
reply.content.append(content.str());
reply.content.append("</body></html>");
}
private:
std::string descriptor_string;
};
#endif /* HELLOWORLDPLUGIN_H_ */
-104
View File
@@ -1,104 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef LOCATEPLUGIN_H_
#define LOCATEPLUGIN_H_
#include "BasePlugin.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/StringUtil.h"
/*
* This Plugin locates the nearest node in the road network for a given coordinate.
*/
class LocatePlugin : public BasePlugin {
public:
LocatePlugin(QueryObjectsStorage * objects) : descriptor_string("locate") {
nodeHelpDesk = objects->nodeHelpDesk;
}
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
if(false == checkCoord(routeParameters.coordinates[0])) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
//query to helpdesk
FixedPointCoordinate result;
std::string tmp;
//json
// JSONParameter = routeParameters.options.Find("jsonp");
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
if(!nodeHelpDesk->FindNearestNodeCoordForLatLon(routeParameters.coordinates[0], result)) {
reply.content += ("\"status\":207,");
reply.content += ("\"mapped_coordinate\":[]");
} else {
//Write coordinate to stream
reply.status = http::Reply::ok;
reply.content += ("\"status\":0,");
reply.content += ("\"mapped_coordinate\":");
convertInternalLatLonToString(result.lat, tmp);
reply.content += "[";
reply.content += tmp;
convertInternalLatLonToString(result.lon, tmp);
reply.content += ",";
reply.content += tmp;
reply.content += "]";
}
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.json\"";
}
reply.headers[0].name = "Content-Length";
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
return;
}
private:
NodeInformationHelpDesk * nodeHelpDesk;
std::string descriptor_string;
};
#endif /* LOCATEPLUGIN_H_ */
-118
View File
@@ -1,118 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef NearestPlugin_H_
#define NearestPlugin_H_
#include "BasePlugin.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/StringUtil.h"
/*
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/
class NearestPlugin : public BasePlugin {
public:
NearestPlugin(QueryObjectsStorage * objects )
:
names(objects->names),
descriptor_string("nearest")
{
nodeHelpDesk = objects->nodeHelpDesk;
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
descriptorTable.insert(std::make_pair("json", 1));
}
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
if(false == checkCoord(routeParameters.coordinates[0])) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
//query to helpdesk
PhantomNode result;
nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
std::string tmp;
//json
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
reply.content += ("\"status\":");
if(UINT_MAX != result.edgeBasedNode)
reply.content += "0,";
else
reply.content += "207,";
reply.content += ("\"mapped_coordinate\":");
reply.content += "[";
if(UINT_MAX != result.edgeBasedNode) {
convertInternalLatLonToString(result.location.lat, tmp);
reply.content += tmp;
convertInternalLatLonToString(result.location.lon, tmp);
reply.content += ",";
reply.content += tmp;
}
reply.content += "],";
reply.content += "\"name\":\"";
if(UINT_MAX != result.edgeBasedNode)
reply.content += names[result.nodeBasedEdgeNameID];
reply.content += "\"";
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.json\"";
}
reply.headers[0].name = "Content-Length";
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
}
private:
NodeInformationHelpDesk * nodeHelpDesk;
HashTable<std::string, unsigned> descriptorTable;
std::vector<std::string> & names;
std::string descriptor_string;
};
#endif /* NearestPlugin_H_ */
-73
View File
@@ -1,73 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TIMESTAMPPLUGIN_H_
#define TIMESTAMPPLUGIN_H_
#include "BasePlugin.h"
class TimestampPlugin : public BasePlugin {
public:
TimestampPlugin(QueryObjectsStorage * o)
: objects(o), descriptor_string("timestamp")
{ }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
std::string tmp;
//json
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
reply.content += ("\"status\":");
reply.content += "0,";
reply.content += ("\"timestamp\":\"");
reply.content += objects->timestamp;
reply.content += "\"";
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"timestamp.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
}
reply.headers[0].name = "Content-Length";
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
}
private:
QueryObjectsStorage * objects;
std::string descriptor_string;
};
#endif /* TIMESTAMPPLUGIN_H_ */
-216
View File
@@ -1,216 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef VIAROUTEPLUGIN_H_
#define VIAROUTEPLUGIN_H_
#include "BasePlugin.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/StaticGraph.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <cstdlib>
#include <string>
#include <vector>
class ViaRoutePlugin : public BasePlugin {
private:
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> & names;
StaticGraph<QueryEdge::EdgeData> * graph;
HashTable<std::string, unsigned> descriptorTable;
SearchEngine * searchEnginePtr;
public:
ViaRoutePlugin(QueryObjectsStorage * objects)
:
names(objects->names),
descriptor_string("viaroute")
{
nodeHelpDesk = objects->nodeHelpDesk;
graph = objects->graph;
searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names);
descriptorTable.insert(std::make_pair("" , 0));
descriptorTable.insert(std::make_pair("json", 0));
descriptorTable.insert(std::make_pair("gpx" , 1));
}
virtual ~ViaRoutePlugin() {
delete searchEnginePtr;
}
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
//check number of parameters
if( 2 > routeParameters.coordinates.size() ) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
RawRouteData rawRoute;
rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
std::vector<std::string> textCoord;
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
if(false == checkCoord(routeParameters.coordinates[i])) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
}
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
continue;
}
}
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
}
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
PhantomNodes segmentPhantomNodes;
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
}
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
// SimpleLogger().Write() << "Checking for alternative paths";
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
} else {
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
}
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
}
reply.status = http::Reply::ok;
//TODO: Move to member as smart pointer
BaseDescriptor * desc;
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
_DescriptorConfig descriptorConfig;
unsigned descriptorType = descriptorTable[routeParameters.outputFormat];
descriptorConfig.z = routeParameters.zoomLevel;
descriptorConfig.instructions = routeParameters.printInstructions;
descriptorConfig.geometry = routeParameters.geometry;
descriptorConfig.encodeGeometry = routeParameters.compression;
switch(descriptorType){
case 0:
desc = new JSONDescriptor();
break;
case 1:
desc = new GPXDescriptor();
break;
default:
desc = new JSONDescriptor();
break;
}
PhantomNodes phantomNodes;
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
// SimpleLogger().Write() << "Start location: " << phantomNodes.startPhantom.location;
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
// SimpleLogger().Write() << "TargetLocation: " << phantomNodes.targetPhantom.location;
// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size();
desc->SetConfig(descriptorConfig);
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
if("" != routeParameters.jsonpParameter) {
reply.content += ")\n";
}
reply.headers.resize(3);
reply.headers[0].name = "Content-Length";
std::string tmp;
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
switch(descriptorType){
case 0:
if("" != routeParameters.jsonpParameter){
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
case 1:
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
break;
default:
if("" != routeParameters.jsonpParameter){
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
}
delete desc;
return;
}
private:
std::string descriptor_string;
};
#endif /* VIAROUTEPLUGIN_H_ */
-7
View File
@@ -1,7 +0,0 @@
For instructions on how to compile and run OSRM, please consult the Wiki at
https://github.com/DennisOSRM/Project-OSRM/wiki
or use our free and daily updated online service at
http://map.project-osrm.org
+46 -31
View File
@@ -1,40 +1,55 @@
# Readme
Overview
--------
The repository provides a Leaflet [(1)] based web frontend to the Open Source Routing Machine (Project-OSRM [(2)]).
The frontend is implemented in Javascript.
Data is fetched from routing and geocoding servers using JSONP queries.
The website is XHTML 1.0 Strict compliant.
A deployed version of the the web frontend can be seen at [(3)].
For instructions on how to compile and run OSRM, please consult the Wiki at
https://github.com/DennisOSRM/Project-OSRM/wiki
Setup
-----
The frontend should work directly as provided.
Several settings - including the URL for the routing server and the geocoder server - can be specified in `OSRM.config.js`.
Different tile servers can be specified in `OSRM.Map.js`.
Note that the URL shortener used for generating route links only works with URLs pointing to the official Project-OSRM website.
or use our free and daily updated online service at
http://map.project-osrm.org
Branches
--------
* The `master` branch will always point to the latest released version of the frontend.
* The `develop` branch should always point to a working version with new features and bugfixes (think of it as a nightly-build).
* Other branches contain various work in progress.
## References in publications
When using the code in a (scientific) publication, please cite
Bugtracking
-----------
Please use the OSRM-Project bug tracker [(4)] for submitting any bug reports or feature requests.
```
@inproceedings{luxen-vetter-2011,
author = {Luxen, Dennis and Vetter, Christian},
title = {Real-time routing with OpenStreetMap data},
booktitle = {Proceedings of the 19th ACM SIGSPATIAL International Conference on Advances in Geographic Information Systems},
series = {GIS '11},
year = {2011},
isbn = {978-1-4503-1031-4},
location = {Chicago, Illinois},
pages = {513--516},
numpages = {4},
url = {http://doi.acm.org/10.1145/2093973.2094062},
doi = {10.1145/2093973.2094062},
acmid = {2094062},
publisher = {ACM},
address = {New York, NY, USA},
}
```
Integration into Project-OSRM repository
----------------------------------------
The Project-OSRM repository already contains the frontend repository as a submodule.
It will always point to the latest deployed version.
To successfully work a repository that contains submodules, use the following git commands (available in git 1.7.1+):
## Current build status
* `git clone --recursive`
to clone a repository and the contained submodules
| build config | branch | status |
|:-------------|:--------|:------------|
| Project OSRM | master | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Project OSRM | develop | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| LUAbind fork | master | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
* `git pull && git submodule update`
to pull the latest version of the repository and update its submodules if required
Note that the frontend can also be checked out independently of the Project-OSRM repository.
References
----------
[(1)] Cloudmade Leaflet: http://leaflet.cloudmade.com/
[(2)] Project OSRM: http://project-osrm.org/
[(3)] Project OSRM Frontend: http://map.project-osrm.org/
[(4)] Project OSRM Bugtracker: https://github.com/DennisOSRM/Project-OSRM/issues/
[(1)]: http://leaflet.cloudmade.com/ "Cloudmade Leaflet"
[(2)]: http://project-osrm.org/ "Project OSRM"
[(3)]: http://map.project-osrm.org/ "Project-OSRM Frontend"
[(4)]: https://github.com/DennisOSRM/Project-OSRM/issues/ "Project-OSRM Bugtracker"
-215
View File
@@ -1,215 +0,0 @@
require 'OSM/StreamParser'
require 'socket'
require 'digest/sha1'
require 'cucumber/rake/task'
require 'sys/proctable'
BUILD_FOLDER = 'build'
DATA_FOLDER = 'sandbox'
PROFILE = 'bicycle'
OSRM_PORT = 5000
PROFILES_FOLDER = '../profiles'
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--format pretty}
end
areas = {
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
:denmark => { :country => 'denmark', :bbox => nil },
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
}
osm_data_area_name = ARGV[1] ? ARGV[1].to_s.to_sym : :kbh
raise "Unknown data area." unless areas[osm_data_area_name]
osm_data_country = areas[osm_data_area_name][:country]
osm_data_area_bbox = areas[osm_data_area_name][:bbox]
task osm_data_area_name.to_sym {} #define empty task to prevent rake from whining. will break if area has same name as a task
def each_process name, &block
Sys::ProcTable.ps do |process|
if process.comm.strip == name.strip && process.state != 'zombie'
yield process.pid.to_i, process.state.strip
end
end
end
def up?
find_pid('osrm-routed') != nil
end
def find_pid name
each_process(name) { |pid,state| return pid.to_i }
return nil
end
def wait_for_shutdown name
timeout = 10
(timeout*10).times do
return if find_pid(name) == nil
sleep 0.1
end
raise "*** Could not terminate #{name}."
end
def write_server_ini osm_file
s=<<-EOF
Threads = 1
IP = 0.0.0.0
Port = #{OSRM_PORT}
hsgrData=#{osm_file}.osrm.hsgr
nodesData=#{osm_file}.osrm.nodes
edgesData=#{osm_file}.osrm.edges
ramIndex=#{osm_file}.osrm.ramIndex
fileIndex=#{osm_file}.osrm.fileIndex
namesData=#{osm_file}.osrm.names
timestamp=#{osm_file}.osrm.timestamp
EOF
File.open( 'server.ini', 'w') {|f| f.write( s ) }
end
desc "Rebuild and run tests."
task :default => [:build]
desc "Build using CMake."
task :build do
if Dir.exists? BUILD_FOLDER
Dir.chdir BUILD_FOLDER do
system "make"
end
else
system "mkdir build; cd build; cmake ..; make"
end
end
desc "Setup config files."
task :setup do
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
['server.ini','extractor.ini','contractor.ini'].each do |file|
unless File.exist? "#{DATA_FOLDER}/#{file}"
puts "Copying #{file} template to #{DATA_FOLDER}/#{file}"
FileUtils.cp file, "#{DATA_FOLDER}/#{file}"
end
end
end
desc "Download OSM data."
task :download => :setup do
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
puts "Downloading..."
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
if osm_data_area_bbox
puts "Cropping and converting to protobuffer..."
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
end
end
desc "Crop OSM data"
task :crop do
if osm_data_area_bbox
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
end
end
desc "Reprocess OSM data."
task :process => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
puts
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
puts
end
end
desc "Extract OSM data."
task :extract => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
end
end
desc "Prepare OSM data."
task :prepare => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
end
end
desc "Delete preprocessing files."
task :clean do
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm.*")
end
desc "Run all cucumber test"
task :test do
system "cucumber"
puts
end
desc "Run the routing server in the terminal. Press Ctrl-C to stop."
task :run => :setup do
Dir.chdir DATA_FOLDER do
write_server_ini osm_data_area_name
system "../#{BUILD_FOLDER}/osrm-routed"
end
end
desc "Launch the routing server in the background. Use rake:down to stop it."
task :up => :setup do
Dir.chdir DATA_FOLDER do
abort("Already up.") if up?
write_server_ini osm_data_area_name
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log")
timeout = 5
(timeout*10).times do
begin
socket = TCPSocket.new('localhost', OSRM_PORT)
socket.puts 'ping'
rescue Errno::ECONNREFUSED
sleep 0.1
end
end
end
end
desc "Stop the routing server."
task :down do
pid = find_pid 'osrm-routed'
if pid
Process.kill 'TERM', pid
else
puts "Already down."
end
end
desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
task :kill do
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
wait_for_shutdown 'osrm-routed'
wait_for_shutdown 'osrm-prepare'
wait_for_shutdown 'osrm-extract'
end
desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
task :pid do
each_process 'osrm-routed' do |pid,state|
puts "#{pid}\t#{state}"
end
end
desc "Stop, reprocess and restart."
task :update => [:down,:process,:up] do
end
-534
View File
@@ -1,534 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef ALTERNATIVEROUTES_H_
#define ALTERNATIVEROUTES_H_
#include "BasicRoutingInterface.h"
#include <boost/unordered_map.hpp>
#include <cmath>
#include <vector>
const double VIAPATH_ALPHA = 0.15;
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
template<class QueryDataT>
class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::Graph SearchGraph;
typedef typename QueryDataT::QueryHeap QueryHeap;
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
struct RankedCandidateNode {
RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {}
NodeID node;
int length;
int sharing;
bool operator<(const RankedCandidateNode& other) const {
return (2*length + sharing) < (2*other.length + other.sharing);
}
};
const SearchGraph * search_graph;
public:
AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
~AlternativeRouting() {}
void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
std::vector<NodeID> alternativePath;
std::vector<NodeID> viaNodeCandidates;
std::vector<SearchSpaceEdge> forward_search_space;
std::vector<SearchSpaceEdge> reverse_search_space;
//Initialize Queues, semi-expensive because access to TSS invokes a system call
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
int upper_bound_to_shortest_path_distance = INT_MAX;
NodeID middle_node = UINT_MAX;
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
if(phantomNodePair.startPhantom.isBidirected() ) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
}
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
if(phantomNodePair.targetPhantom.isBidirected() ) {
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
}
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
if(0 < forward_heap1.Size()){
AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
}
if(0 < reverse_heap1.Size()){
AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
}
}
sort_unique_resize(viaNodeCandidates);
std::vector<NodeID> packed_forward_path;
std::vector<NodeID> packed_reverse_path;
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
boost::unordered_map<NodeID, int> approximated_forward_sharing;
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
unsigned index_into_forward_path = 0;
//sweep over search space, compute forward sharing for each current edge (u,v)
BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) {
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) {
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_forward_path;
approximated_forward_sharing[v] = forward_heap1.GetKey(u);
} else {
//sharing (s) = sharing (t)
approximated_forward_sharing[v] = approximated_forward_sharing[u];
}
}
unsigned index_into_reverse_path = 0;
//sweep over search space, compute backward sharing
BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) {
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) {
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_reverse_path;
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
} else {
//sharing (s) = sharing (t)
approximated_reverse_sharing[v] = approximated_reverse_sharing[u];
}
}
std::vector<NodeID> nodes_that_passed_preselection;
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA);
bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing);
if(lengthPassed && sharingPassed && stretchPassed) {
nodes_that_passed_preselection.push_back(node);
}
}
std::vector<NodeID> & packedShortestPath = packed_forward_path;
std::reverse(packedShortestPath.begin(), packedShortestPath.end());
packedShortestPath.push_back(middle_node);
packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end());
std::vector<RankedCandidateNode > rankedCandidates;
//prioritizing via nodes for deep inspection
BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) {
int lengthOfViaPath = 0, sharingOfViaPath = 0;
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath);
if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) {
rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath));
}
}
std::sort(rankedCandidates.begin(), rankedCandidates.end());
NodeID selectedViaNode = UINT_MAX;
int lengthOfViaPath = INT_MAX;
NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){
if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
// select first admissable
selectedViaNode = candidate.node;
break;
}
}
//Unpack shortest path and alternative, if they exist
if(INT_MAX != upper_bound_to_shortest_path_distance) {
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
} else {
rawRouteData.lengthOfShortestPath = INT_MAX;
}
if(selectedViaNode != UINT_MAX) {
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
} else {
rawRouteData.lengthOfAlternativePath = INT_MAX;
}
}
private:
//unpack <s,..,v,..,t> by exploring search spaces from v
inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2,
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
//unpack [s,v)
std::vector<NodeID> packed_s_v_path, packed_v_t_path;
super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path);
packed_s_v_path.resize(packed_s_v_path.size()-1);
//unpack [v,t]
super::RetrievePackedPathFromHeap(_forwardHeap2, _backwardHeap1, v_t_middle, packed_v_t_path);
packed_s_v_path.insert(packed_s_v_path.end(),packed_v_t_path.begin(), packed_v_t_path.end() );
super::UnpackPath(packed_s_v_path, unpackedPath);
}
inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path,
const int offset, const std::vector<NodeID> & packed_shortest_path) {
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
//only half-searches have to be done at this stage
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2;
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
std::vector<NodeID> partiallyUnpackedShortestPath;
std::vector<NodeID> partiallyUnpackedViaPath;
NodeID s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
newBackwardHeap.Insert(via_node, 0, via_node);
while (0 < newBackwardHeap.Size()) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
}
//compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap.Insert(via_node, 0, via_node);
while (0 < newForwardHeap.Size() ) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
}
*real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
return;
//retrieve packed paths
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path);
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle, packed_v_t_path);
//partial unpacking, compute sharing
//First partially unpack s-->v until paths deviate, note length of common path.
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} else {
if (packed_s_v_path[i] == packed_shortest_path[i]) {
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath);
break;
}
}
}
//traverse partially unpacked edge and note common prefix
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
}
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
int viaPathIndex = packed_v_t_path.size() - 1;
int shortestPathIndex = packed_shortest_path.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} else {
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath);
break;
}
}
}
viaPathIndex = partiallyUnpackedViaPath.size() - 1;
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} else {
break;
}
}
//finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable
}
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
std::vector<NodeID> packedAlternativePath;
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2)
return 0;
int sharing = 0;
int aindex = 0;
//compute forward sharing
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += search_graph->GetEdgeData(edgeID).distance;
++aindex;
}
aindex = packedAlternativePath.size()-1;
int bindex = packedShortestPath.size()-1;
//compute backward sharing
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += search_graph->GetEdgeData(edgeID).distance;
--aindex; --bindex;
}
return sharing;
}
template<bool forwardDirection>
inline void AlternativeRoutingStep(
QueryHeap & _forward_heap,
QueryHeap & _reverse_heap,
NodeID *middle_node,
int *upper_bound_to_shortest_path_distance,
std::vector<NodeID>& searchSpaceIntersection,
std::vector<SearchSpaceEdge> & search_space,
const int edgeBasedOffset
) const {
const NodeID node = _forward_heap.DeleteMin();
const int distance = _forward_heap.GetKey(node);
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
if(scaledDistance > *upper_bound_to_shortest_path_distance){
_forward_heap.DeleteAll();
return;
}
search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node));
if(_reverse_heap.WasInserted(node) ){
searchSpaceIntersection.push_back(node);
const int newDistance = _reverse_heap.GetKey(node) + distance;
if(newDistance < *upper_bound_to_shortest_path_distance ){
if(newDistance>=0 ) {
*middle_node = node;
*upper_bound_to_shortest_path_distance = newDistance;
}
}
}
for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = search_graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forward_heap.WasInserted( to ) ) {
_forward_heap.Insert( to, toDistance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forward_heap.GetKey( to ) ) {
_forward_heap.GetData( to ).parent = node;
_forward_heap.DecreaseKey( to, toDistance );
//new parent
}
}
}
}
//conduct T-Test
inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
newForwardHeap.Clear();
newBackwardHeap.Clear();
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
*s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;
//compute path <s,..,v> by reusing forward search from s
newBackwardHeap.Insert(candidate.node, 0, candidate.node);
while (newBackwardHeap.Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
}
if(INT_MAX == upperBoundFor_s_v_Path)
return false;
//compute path <v,..,t> by reusing backward search from t
*v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap.Insert(candidate.node, 0, candidate.node);
while (newForwardHeap.Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
}
if(INT_MAX == upperBoundFor_v_t_Path)
return false;
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
//retrieve packed paths
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, *s_v_middle, packed_s_v_path);
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path);
NodeID s_P = *s_v_middle, t_P = *v_t_middle;
if(UINT_MAX == s_P) {
return false;
}
if(UINT_MAX == t_P) {
return false;
}
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
int unpackedUntilDistance = 0;
std::stack<SearchSpaceEdge> unpackStack;
//Traverse path s-->v
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
} else {
unpackedUntilDistance += lengthOfCurrentEdge;
s_P = packed_s_v_path[i - 1];
}
}
while (!unpackStack.empty()) {
const SearchSpaceEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
//attention: !unpacking in reverse!
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
} else {
unpackedUntilDistance += lengthOfSecondSegment;
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
}
} else {
// edge is not a shortcut, set the start node for T-Test to end of edge.
unpackedUntilDistance += currentEdgeData.distance;
s_P = viaPathEdge.first;
}
}
int lengthOfPathT_Test_Path = unpackedUntilDistance;
unpackedUntilDistance = 0;
//Traverse path s-->v
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
} else {
unpackedUntilDistance += lengthOfCurrentEdge;
t_P = packed_v_t_path[i + 1];
}
}
while (!unpackStack.empty()) {
const SearchSpaceEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance;
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
} else {
unpackedUntilDistance += lengthOfFirstSegment;
unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second));
}
} else {
// edge is not a shortcut, set the start node for T-Test to end of edge.
unpackedUntilDistance += currentEdgeData.distance;
t_P = viaPathEdge.second;
}
}
lengthOfPathT_Test_Path += unpackedUntilDistance;
//Run actual T-Test query and compare if distances equal.
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
int _upperBound = INT_MAX;
NodeID middle = UINT_MAX;
forward_heap3.Insert(s_P, 0, s_P);
backward_heap3.Insert(t_P, 0, t_P);
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while (forward_heap3.Size() + backward_heap3.Size() > 0) {
if (forward_heap3.Size() > 0) {
super::RoutingStep(forward_heap3, backward_heap3, &middle, &_upperBound, offset, true);
}
if (backward_heap3.Size() > 0) {
super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
}
}
return (_upperBound <= lengthOfPathT_Test_Path);
}
};
#endif /* ALTERNATIVEROUTES_H_ */
-226
View File
@@ -1,226 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASICROUTINGINTERFACE_H_
#define BASICROUTINGINTERFACE_H_
#include "../DataStructures/RawRouteData.h"
#include "../Util/ContainerUtils.h"
#include "../Util/SimpleLogger.h"
#include <boost/noncopyable.hpp>
#include <cassert>
#include <climits>
#include <stack>
template<class QueryDataT>
class BasicRoutingInterface : boost::noncopyable{
protected:
QueryDataT & _queryData;
public:
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
virtual ~BasicRoutingInterface(){ };
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
const NodeID node = _forwardHeap.DeleteMin();
const int distance = _forwardHeap.GetKey(node);
//SimpleLogger().Write() << "Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance;
if(_backwardHeap.WasInserted(node) ){
const int newDistance = _backwardHeap.GetKey(node) + distance;
if(newDistance < *_upperbound ){
if(newDistance>=0 ) {
*middle = node;
*_upperbound = newDistance;
} else {
}
}
}
if(distance-edgeBasedOffset > *_upperbound){
_forwardHeap.DeleteAll();
return;
}
//Stalling
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) {
const NodeID to = _queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
if(_forwardHeap.WasInserted( to )) {
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
return;
}
}
}
}
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = _queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap.WasInserted( to ) ) {
_forwardHeap.Insert( to, toDistance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap.GetKey( to ) ) {
_forwardHeap.GetData( to ).parent = node;
_forwardHeap.DecreaseKey( to, toDistance );
//new parent
}
}
}
}
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const unsigned sizeOfPackedPath = packedPath.size();
std::stack<std::pair<NodeID, NodeID> > recursionStack;
//We have to push the path in reverse order onto the stack because it's LIFO.
for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
}
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
//again, we need to this in reversed order
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
} else {
assert(!ed.shortcut);
unpackedPath.push_back(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance) );
}
}
}
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
std::stack<std::pair<NodeID, NodeID> > recursionStack;
recursionStack.push(std::make_pair(s,t));
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
//again, we need to this in reversed order
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
} else {
assert(!ed.shortcut);
unpackedPath.push_back(edge.first );
}
}
unpackedPath.push_back(t);
}
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
NodeID pathNode = middle;
while(pathNode != _fHeap.GetData(pathNode).parent) {
pathNode = _fHeap.GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
std::reverse(packedPath.begin(), packedPath.end());
packedPath.push_back(middle);
pathNode = middle;
while (pathNode != _bHeap.GetData(pathNode).parent){
pathNode = _bHeap.GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
}
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
NodeID pathNode = middle;
while(pathNode != search_heap.GetData(pathNode).parent) {
pathNode = search_heap.GetData(pathNode).parent;
packed_path.push_back(pathNode);
}
}
};
#endif /* BASICROUTINGINTERFACE_H_ */
-201
View File
@@ -1,201 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SHORTESTPATHROUTING_H_
#define SHORTESTPATHROUTING_H_
#include "BasicRoutingInterface.h"
template<class QueryDataT>
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::QueryHeap QueryHeap;
public:
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
~ShortestPathRouting() {}
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
}
int distance1 = 0;
int distance2 = 0;
bool searchFrom1stStartNode = true;
bool searchFrom2ndStartNode = true;
NodeID middle1 = UINT_MAX;
NodeID middle2 = UINT_MAX;
std::vector<NodeID> packedPath1;
std::vector<NodeID> packedPath2;
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
//Get distance to next pair of target nodes.
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
forward_heap1.Clear(); forward_heap2.Clear();
reverse_heap1.Clear(); reverse_heap2.Clear();
int _localUpperbound1 = INT_MAX;
int _localUpperbound2 = INT_MAX;
middle1 = UINT_MAX;
middle2 = UINT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances.
if(searchFrom1stStartNode) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
}
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
}
//insert new backward nodes into backward heap, unadjusted.
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
if(phantomNodePair.targetPhantom.isBidirected() ) {
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
// INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
}
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
//run two-Target Dijkstra routing step.
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
if(0 < forward_heap1.Size()){
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
}
if(0 < reverse_heap1.Size() ){
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
}
}
if(0 < reverse_heap2.Size()) {
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
if(0 < forward_heap2.Size()){
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
}
if(0 < reverse_heap2.Size()){
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
}
}
}
//No path found for both target nodes?
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
if(UINT_MAX == middle1) {
searchFrom1stStartNode = false;
}
if(UINT_MAX == middle2) {
searchFrom2ndStartNode = false;
}
//Was at most one of the two paths not found?
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
//Unpack paths if they exist
std::vector<NodeID> temporaryPackedPath1;
std::vector<NodeID> temporaryPackedPath2;
if(INT_MAX != _localUpperbound1) {
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
}
if(INT_MAX != _localUpperbound2) {
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
}
//if one of the paths was not found, replace it with the other one.
if(0 == temporaryPackedPath1.size()) {
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
_localUpperbound1 = _localUpperbound2;
}
if(0 == temporaryPackedPath2.size()) {
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
_localUpperbound2 = _localUpperbound1;
}
assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
//Plug paths together, s.t. end of packed path is begin of temporary packed path
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
//both new route segments start with the same node, thus one of the packedPath must go.
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
packedPath2.clear();
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
distance2 = distance1;
} else {
packedPath1.clear();
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
distance1 = distance2;
}
} else {
//packed paths 1 and 2 may need to switch.
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
packedPath1.swap(packedPath2);
std::swap(distance1, distance2);
}
}
}
packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
NodeID lastNodeID = packedPath2.back();
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
}
distance1 += _localUpperbound1;
distance2 += _localUpperbound2;
}
if(distance1 > distance2){
std::swap(packedPath1, packedPath2);
}
remove_consecutive_duplicates_from_vector(packedPath1);
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
return;
}
};
#endif /* SHORTESTPATHROUTING_H_ */
-63
View File
@@ -1,63 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef APIGRAMMAR_H_
#define APIGRAMMAR_H_
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_action.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator, class HandlerT>
struct APIGrammar : qi::grammar<Iterator> {
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithDot[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
location = (-qi::lit('&')) >> qi::lit("loc") >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)];
hint = (-qi::lit('&')) >> qi::lit("hint") >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)];
language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)];
alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
string = +(qi::char_("a-zA-Z"));
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
}
qi::rule<Iterator> api_call, query;
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
stringwithDot, language, instruction, geometry,
cmp, alt_route, old_API;
HandlerT * handler;
};
#endif /* APIGRAMMAR_H_ */
-161
View File
@@ -1,161 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASIC_DATASTRUCTURES_H
#define BASIC_DATASTRUCTURES_H
#include "../Util/StringUtil.h"
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <string>
#include <sstream>
#include <vector>
namespace http {
const std::string okString = "HTTP/1.0 200 OK\r\n";
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
const char okHTML[] = "";
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
const char seperators[] = { ':', ' ' };
const char crlf[] = { '\r', '\n' };
struct Header {
std::string name;
std::string value;
void Clear() {
name.clear();
value.clear();
}
};
enum CompressionType {
noCompression,
gzipRFC1952,
deflateRFC1951
} Compression;
struct Request {
std::string uri;
std::string referrer;
std::string agent;
boost::asio::ip::address endpoint;
};
struct Reply {
Reply() : status(ok) { content.reserve(2 << 20); }
enum status_type {
ok = 200,
badRequest = 400,
internalServerError = 500
} status;
std::vector<Header> headers;
std::vector<boost::asio::const_buffer> toBuffers();
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
std::string content;
static Reply stockReply(status_type status);
void setSize(const unsigned size) {
BOOST_FOREACH ( Header& h, headers) {
if("Content-Length" == h.name) {
std::string sizeString;
intToString(size,h.value);
}
}
}
};
boost::asio::const_buffer ToBuffer(Reply::status_type status) {
switch (status) {
case Reply::ok:
return boost::asio::buffer(okString);
case Reply::internalServerError:
return boost::asio::buffer(internalServerErrorString);
default:
return boost::asio::buffer(badRequestString);
}
}
std::string ToString(Reply::status_type status) {
switch (status) {
case Reply::ok:
return okHTML;
case Reply::badRequest:
return badRequestHTML;
default:
return internalServerErrorHTML;
}
}
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(ToBuffer(status));
for (std::size_t i = 0; i < headers.size(); ++i) {
Header& h = headers[i];
buffers.push_back(boost::asio::buffer(h.name));
buffers.push_back(boost::asio::buffer(seperators));
buffers.push_back(boost::asio::buffer(h.value));
buffers.push_back(boost::asio::buffer(crlf));
}
buffers.push_back(boost::asio::buffer(crlf));
buffers.push_back(boost::asio::buffer(content));
return buffers;
}
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(ToBuffer(status));
for (std::size_t i = 0; i < headers.size(); ++i) {
Header& h = headers[i];
// std::cout << h.name << ": " << h.value << std::endl;
buffers.push_back(boost::asio::buffer(h.name));
buffers.push_back(boost::asio::buffer(seperators));
buffers.push_back(boost::asio::buffer(h.value));
buffers.push_back(boost::asio::buffer(crlf));
}
buffers.push_back(boost::asio::buffer(crlf));
return buffers;
}
Reply Reply::stockReply(Reply::status_type status) {
Reply rep;
rep.status = status;
rep.content = ToString(status);
rep.headers.resize(3);
rep.headers[0].name = "Access-Control-Allow-Origin";
rep.headers[0].value = "*";
rep.headers[1].name = "Content-Length";
std::string s;
intToString(rep.content.size(), s);
rep.headers[1].value = s;
rep.headers[2].name = "Content-Type";
rep.headers[2].value = "text/html";
return rep;
}
} // namespace http
#endif //BASIC_DATASTRUCTURES_H
-181
View File
@@ -1,181 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONNECTION_H
#define CONNECTION_H
#include "BasicDatastructures.h"
#include "RequestHandler.h"
#include "RequestParser.h"
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <zlib.h>
#include <vector>
namespace http {
/// Represents a single connection from a client.
class Connection : public boost::enable_shared_from_this<Connection>, private boost::noncopyable {
public:
explicit Connection(boost::asio::io_service& io_service, RequestHandler& handler) : strand(io_service), TCPsocket(io_service), requestHandler(handler) {}
boost::asio::ip::tcp::socket& socket() {
return TCPsocket;
}
/// Start the first asynchronous operation for the connection.
void start() {
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
private:
void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred) {
if (!e) {
CompressionType compressionType(noCompression);
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = requestParser.Parse( request, incomingDataBuffer.data(), incomingDataBuffer.data() + bytes_transferred, &compressionType);
if (result) {
// std::cout << "----" << std::endl;
// if(compressionType == gzipRFC1952)
// std::cout << "[debug] using gzip" << std::endl;
// if(compressionType == deflateRFC1951)
// std::cout << "[debug] using deflate" << std::endl;
// if(compressionType == noCompression)
// std::cout << "[debug] no compression" << std::endl;
request.endpoint = TCPsocket.remote_endpoint().address();
requestHandler.handle_request(request, reply);
Header compressionHeader;
std::vector<unsigned char> compressed;
std::vector<boost::asio::const_buffer> outputBuffer;
switch(compressionType) {
case deflateRFC1951:
compressionHeader.name = "Content-Encoding";
compressionHeader.value = "deflate";
reply.headers.insert(reply.headers.begin(), compressionHeader); //push_back(compressionHeader);
compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
reply.setSize(compressed.size());
outputBuffer = reply.HeaderstoBuffers();
outputBuffer.push_back(boost::asio::buffer(compressed));
boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
break;
case gzipRFC1952:
compressionHeader.name = "Content-Encoding";
compressionHeader.value = "gzip";
reply.headers.insert(reply.headers.begin(), compressionHeader);
compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
reply.setSize(compressed.size());
outputBuffer = reply.HeaderstoBuffers();
outputBuffer.push_back(boost::asio::buffer(compressed));
boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));break;
case noCompression:
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
break;
}
} else if (!result) {
reply = Reply::stockReply(Reply::badRequest);
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
} else {
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
}
}
/// Handle completion of a write operation.
void handleWrite(const boost::system::error_code& e) {
if (!e) {
// Initiate graceful connection closure.
boost::system::error_code ignoredEC;
TCPsocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC);
}
// No new asynchronous operations are started. This means that all shared_ptr
// references to the connection object will disappear and the object will be
// destroyed automatically after this handler returns. The connection class's
// destructor closes the socket.
}
void compressCharArray(const void *in_data, size_t in_data_size, std::vector<unsigned char> &buffer, CompressionType type) {
const size_t BUFSIZE = 128 * 1024;
unsigned char temp_buffer[BUFSIZE];
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in = (unsigned char *)(in_data);
strm.avail_in = in_data_size;
strm.next_out = temp_buffer;
strm.avail_out = BUFSIZE;
strm.data_type = Z_ASCII;
switch(type){
case deflateRFC1951:
deflateInit(&strm, Z_BEST_SPEED);
break;
case gzipRFC1952:
/*
* Big thanks to deusty who explains how to have gzip compression turned on by the right call to deflateInit2():
* http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
*/
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 9, Z_DEFAULT_STRATEGY);
break;
default:
assert(false);
break;
}
int deflate_res = Z_OK;
do {
if (strm.avail_out == 0) {
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
strm.next_out = temp_buffer;
strm.avail_out = BUFSIZE;
}
deflate_res = deflate(&strm, Z_FINISH);
} while (deflate_res == Z_OK);
assert(deflate_res == Z_STREAM_END);
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE - strm.avail_out);
deflateEnd(&strm);
}
boost::asio::io_service::strand strand;
boost::asio::ip::tcp::socket TCPsocket;
RequestHandler& requestHandler;
boost::array<char, 8192> incomingDataBuffer;
Request request;
RequestParser requestParser;
Reply reply;
};
} // namespace http
#endif // CONNECTION_H
@@ -1,130 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "QueryObjectsStorage.h"
QueryObjectsStorage::QueryObjectsStorage(
const std::string & hsgrPath,
const std::string & ramIndexPath,
const std::string & fileIndexPath,
const std::string & nodesPath,
const std::string & edgesPath,
const std::string & namesPath,
const std::string & timestampPath
) {
if( hsgrPath.empty() ) {
throw OSRMException("no hsgr file given in ini file");
}
if( ramIndexPath.empty() ) {
throw OSRMException("no ram index file given in ini file");
}
if( fileIndexPath.empty() ) {
throw OSRMException("no mem index file given in ini file");
}
if( nodesPath.empty() ) {
throw OSRMException("no nodes file given in ini file");
}
if( edgesPath.empty() ) {
throw OSRMException("no edges file given in ini file");
}
if( namesPath.empty() ) {
throw OSRMException("no names file given in ini file");
}
SimpleLogger().Write() << "loading graph data";
//Deserialize road network graph
std::vector< QueryGraph::_StrNode> nodeList;
std::vector< QueryGraph::_StrEdge> edgeList;
const int n = readHSGRFromStream(
hsgrPath,
nodeList,
edgeList,
&checkSum
);
SimpleLogger().Write() << "Data checksum is " << checkSum;
graph = new QueryGraph(nodeList, edgeList);
assert(0 == nodeList.size());
assert(0 == edgeList.size());
if(timestampPath.length()) {
SimpleLogger().Write() << "Loading Timestamp";
std::ifstream timestampInStream(timestampPath.c_str());
if(!timestampInStream) {
SimpleLogger().Write(logWARNING) << timestampPath << " not found";
}
getline(timestampInStream, timestamp);
timestampInStream.close();
}
if(!timestamp.length()) {
timestamp = "n/a";
}
if(25 < timestamp.length()) {
timestamp.resize(25);
}
SimpleLogger().Write() << "Loading auxiliary information";
//Init nearest neighbor data structure
nodeHelpDesk = new NodeInformationHelpDesk(
ramIndexPath,
fileIndexPath,
nodesPath,
edgesPath,
n,
checkSum
);
//deserialize street name list
SimpleLogger().Write() << "Loading names index";
boost::filesystem::path names_file(namesPath);
if ( !boost::filesystem::exists( names_file ) ) {
throw OSRMException("names file does not exist");
}
if ( 0 == boost::filesystem::file_size( names_file ) ) {
throw OSRMException("names file is empty");
}
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
unsigned size = 0;
name_stream.read((char *)&size, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != size, "name file empty");
char buf[1024];
for( unsigned i = 0; i < size; ++i ) {
unsigned size_of_string = 0;
name_stream.read((char *)&size_of_string, sizeof(unsigned));
buf[size_of_string] = '\0'; // instead of memset
name_stream.read(buf, size_of_string);
names.push_back(buf);
}
std::vector<std::string>(names).swap(names);
BOOST_ASSERT_MSG(0 != names.size(), "could not load any names");
name_stream.close();
SimpleLogger().Write() << "All query data structures loaded";
}
QueryObjectsStorage::~QueryObjectsStorage() {
// delete names;
delete graph;
delete nodeHelpDesk;
}
@@ -1,63 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef QUERYOBJECTSSTORAGE_H_
#define QUERYOBJECTSSTORAGE_H_
#include "../../Util/GraphLoader.h"
#include "../../Util/OSRMException.h"
#include "../../Util/SimpleLogger.h"
#include "../../DataStructures/NodeInformationHelpDesk.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <vector>
#include <string>
struct QueryObjectsStorage {
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> names;
QueryGraph * graph;
std::string timestamp;
unsigned checkSum;
QueryObjectsStorage(
const std::string & hsgrPath,
const std::string & ramIndexPath,
const std::string & fileIndexPath,
const std::string & nodesPath,
const std::string & edgesPath,
const std::string & namesPath,
const std::string & timestampPath
);
~QueryObjectsStorage();
};
#endif /* QUERYOBJECTSSTORAGE_H_ */
-116
View File
@@ -1,116 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef ROUTE_PARAMETERS_H
#define ROUTE_PARAMETERS_H
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/HashTable.h"
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <string>
#include <vector>
struct RouteParameters {
RouteParameters() :
zoomLevel(18),
printInstructions(false),
alternateRoute(true),
geometry(true),
compression(true),
deprecatedAPI(false),
checkSum(-1) {}
short zoomLevel;
bool printInstructions;
bool alternateRoute;
bool geometry;
bool compression;
bool deprecatedAPI;
unsigned checkSum;
std::string service;
std::string outputFormat;
std::string jsonpParameter;
std::string language;
std::vector<std::string> hints;
std::vector<FixedPointCoordinate> coordinates;
typedef HashTable<std::string, std::string>::const_iterator OptionsIterator;
void setZoomLevel(const short i) {
if (18 > i && 0 < i) {
zoomLevel = i;
}
}
void setAlternateRouteFlag(const bool b) {
alternateRoute = b;
}
void setDeprecatedAPIFlag(const std::string &) {
deprecatedAPI = true;
}
void setChecksum(const unsigned c) {
checkSum = c;
}
void setInstructionFlag(const bool b) {
printInstructions = b;
}
void setService( const std::string & s) {
service = s;
}
void setOutputFormat(const std::string & s) {
outputFormat = s;
}
void setJSONpParameter(const std::string & s) {
jsonpParameter = s;
}
void addHint(const std::string & s) {
hints.resize(coordinates.size());
hints.back() = s;
}
void setLanguage(const std::string & s) {
language = s;
}
void setGeometryFlag(const bool b) {
geometry = b;
}
void setCompressionFlag(const bool b) {
compression = b;
}
void addCoordinate(const boost::fusion::vector < double, double > & arg_) {
int lat = COORDINATE_PRECISION*boost::fusion::at_c < 0 > (arg_);
int lon = COORDINATE_PRECISION*boost::fusion::at_c < 1 > (arg_);
coordinates.push_back(FixedPointCoordinate(lat, lon));
}
};
#endif /*ROUTE_PARAMETERS_H*/
-112
View File
@@ -1,112 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H
#include "APIGrammar.h"
#include "BasicDatastructures.h"
#include "DataStructures/RouteParameters.h"
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <boost/foreach.hpp>
#include <boost/noncopyable.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
class RequestHandler : private boost::noncopyable {
public:
typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
explicit RequestHandler() { }
void handle_request(const http::Request& req, http::Reply& rep){
//parse command
try {
std::string request(req.uri);
time_t ltime;
struct tm *Tm;
ltime=time(NULL);
Tm=localtime(&ltime);
SimpleLogger().Write() <<
(Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" <<
(Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" <<
1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) <<
Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) <<
Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) <<
Tm->tm_sec << " " << req.endpoint.to_string() << " " <<
req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri;
RouteParameters routeParameters;
APIGrammarParser apiParser(&routeParameters);
std::string::iterator it = request.begin();
const bool result = boost::spirit::qi::parse(
it,
request.end(),
apiParser
);
if ( !result || (it != request.end()) ) {
rep = http::Reply::stockReply(http::Reply::badRequest);
const int position = std::distance(request.begin(), it);
std::string tmp_position_string;
intToString(position, tmp_position_string);
rep.content += "Input seems to be malformed close to position ";
rep.content += "<br><pre>";
rep.content += request;
rep.content += tmp_position_string;
rep.content += "<br>";
const unsigned end = std::distance(request.begin(), it);
for(unsigned i = 0; i < end; ++i) {
rep.content += "&nbsp;";
}
rep.content += "^<br></pre>";
} else {
//parsing done, lets call the right plugin to handle the request
routing_machine->RunQuery(routeParameters, rep);
return;
}
} catch(std::exception& e) {
rep = http::Reply::stockReply(http::Reply::internalServerError);
SimpleLogger().Write(logWARNING) <<
"[server error] code: " << e.what() << ", uri: " << req.uri;
return;
}
};
void RegisterRoutingMachine(OSRM * osrm) {
routing_machine = osrm;
}
private:
OSRM * routing_machine;
};
#endif // REQUEST_HANDLER_H
-292
View File
@@ -1,292 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef REQUEST_PARSER_H
#define REQUEST_PARSER_H
#include "BasicDatastructures.h"
#include <boost/logic/tribool.hpp>
#include <boost/tuple/tuple.hpp>
namespace http {
class RequestParser {
public:
RequestParser() : state_(method_start) { }
void Reset() { state_ = method_start; }
boost::tuple<boost::tribool, char*> Parse(Request& req, char* begin, char* end, CompressionType * compressionType) {
while (begin != end) {
boost::tribool result = consume(req, *begin++, compressionType);
if (result || !result){
return boost::make_tuple(result, begin);
}
}
boost::tribool result = boost::indeterminate;
return boost::make_tuple(result, begin);
}
private:
boost::tribool consume(Request& req, char input, CompressionType * compressionType) {
switch (state_) {
case method_start:
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
state_ = method;
return boost::indeterminate;
}
case method:
if (input == ' ') {
state_ = uri;
return boost::indeterminate;
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
return boost::indeterminate;
}
case uri_start:
if (isCTL(input)) {
return false;
} else {
state_ = uri;
req.uri.push_back(input);
return boost::indeterminate;
}
case uri:
if (input == ' ') {
state_ = http_version_h;
return boost::indeterminate;
} else if (isCTL(input)) {
return false;
} else {
req.uri.push_back(input);
return boost::indeterminate;
}
case http_version_h:
if (input == 'H') {
state_ = http_version_t_1;
return boost::indeterminate;
} else {
return false;
}
case http_version_t_1:
if (input == 'T') {
state_ = http_version_t_2;
return boost::indeterminate;
} else {
return false;
}
case http_version_t_2:
if (input == 'T') {
state_ = http_version_p;
return boost::indeterminate;
} else {
return false;
}
case http_version_p:
if (input == 'P') {
state_ = http_version_slash;
return boost::indeterminate;
} else {
return false;
}
case http_version_slash:
if (input == '/') {
state_ = http_version_major_start;
return boost::indeterminate;
} else {
return false;
}
case http_version_major_start:
if (isDigit(input)) {
state_ = http_version_major;
return boost::indeterminate;
} else {
return false;
}
case http_version_major:
if (input == '.') {
state_ = http_version_minor_start;
return boost::indeterminate;
} else if (isDigit(input)) {
return boost::indeterminate;
} else {
return false;
}
case http_version_minor_start:
if (isDigit(input)) {
state_ = http_version_minor;
return boost::indeterminate;
} else {
return false;
}
case http_version_minor:
if (input == '\r') {
state_ = expecting_newline_1;
return boost::indeterminate;
} else if (isDigit(input)) {
return boost::indeterminate;
}
else {
return false;
}
case expecting_newline_1:
if (input == '\n') {
state_ = header_line_start;
return boost::indeterminate;
} else {
return false;
}
case header_line_start:
if(header.name == "Accept-Encoding") {
/* giving gzip precedence over deflate */
if(header.value.find("deflate") != std::string::npos)
*compressionType = deflateRFC1951;
if(header.value.find("gzip") != std::string::npos)
*compressionType = gzipRFC1952;
}
if("Referer" == header.name)
req.referrer = header.value;
if("User-Agent" == header.name)
req.agent = header.value;
if (input == '\r') {
state_ = expecting_newline_3;
return boost::indeterminate;
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
state_ = header_name;
header.Clear();
header.name.push_back(input);
return boost::indeterminate;
}
case header_lws:
if (input == '\r') {
state_ = expecting_newline_2;
return boost::indeterminate;
} else if (input == ' ' || input == '\t') {
return boost::indeterminate;
}
else if (isCTL(input)) {
return false;
} else {
state_ = header_value;
return boost::indeterminate;
}
case header_name:
if (input == ':') {
state_ = space_before_header_value;
return boost::indeterminate;
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
header.name.push_back(input);
return boost::indeterminate;
}
case space_before_header_value:
if (input == ' ') {
state_ = header_value;
return boost::indeterminate;
} else {
return false;
}
case header_value:
if (input == '\r') {
state_ = expecting_newline_2;
return boost::indeterminate;
} else if (isCTL(input)) {
return false;
} else {
header.value.push_back(input);
return boost::indeterminate;
}
case expecting_newline_2:
if (input == '\n') {
state_ = header_line_start;
return boost::indeterminate;
} else {
return false;
}
case expecting_newline_3:
return (input == '\n');
default:
return false;
}
}
inline bool isChar(int c) {
return c >= 0 && c <= 127;
}
inline bool isCTL(int c) {
return (c >= 0 && c <= 31) || (c == 127);
}
inline bool isTSpecial(int c) {
switch (c) {
case '(': case ')': case '<': case '>': case '@':
case ',': case ';': case ':': case '\\': case '"':
case '/': case '[': case ']': case '?': case '=':
case '{': case '}': case ' ': case '\t':
return true;
default:
return false;
}
}
inline bool isDigit(int c) {
return c >= '0' && c <= '9';
}
enum state {
method_start,
method,
uri_start,
uri,
http_version_h,
http_version_t_1,
http_version_t_2,
http_version_p,
http_version_slash,
http_version_major_start,
http_version_major,
http_version_minor_start,
http_version_minor,
expecting_newline_1,
header_line_start,
header_lws,
header_name,
space_before_header_value,
header_value,
expecting_newline_2,
expecting_newline_3
} state_;
Header header;
};
} // namespace http
#endif // REQUEST_PARSER_H
-108
View File
@@ -1,108 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SERVER_H
#define SERVER_H
#include "Connection.h"
#include "RequestHandler.h"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <vector>
class Server: private boost::noncopyable {
public:
explicit Server(
const std::string& address,
const std::string& port,
unsigned thread_pool_size
) :
threadPoolSize(thread_pool_size),
acceptor(ioService),
newConnection(new http::Connection(ioService, requestHandler)),
requestHandler()
{
boost::asio::ip::tcp::resolver resolver(ioService);
boost::asio::ip::tcp::resolver::query query(address, port);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor.open(endpoint.protocol());
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint);
acceptor.listen();
acceptor.async_accept(
newConnection->socket(),
boost::bind(
&Server::handleAccept,
this,
boost::asio::placeholders::error
)
);
}
void Run() {
std::vector<boost::shared_ptr<boost::thread> > threads;
for (unsigned i = 0; i < threadPoolSize; ++i) {
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService)));
threads.push_back(thread);
}
for (unsigned i = 0; i < threads.size(); ++i)
threads[i]->join();
}
void Stop() {
ioService.stop();
}
RequestHandler & GetRequestHandlerPtr() {
return requestHandler;
}
private:
void handleAccept(const boost::system::error_code& e) {
if (!e) {
newConnection->start();
newConnection.reset(
new http::Connection(ioService, requestHandler)
);
acceptor.async_accept(
newConnection->socket(),
boost::bind(
&Server::handleAccept,
this,
boost::asio::placeholders::error
)
);
}
}
unsigned threadPoolSize;
boost::asio::io_service ioService;
boost::asio::ip::tcp::acceptor acceptor;
boost::shared_ptr<http::Connection> newConnection;
RequestHandler requestHandler;
};
#endif // SERVER_H
-68
View File
@@ -1,68 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SERVERFACTORY_H_
#define SERVERFACTORY_H_
#include "Server.h"
#include "../Util/IniFile.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <zlib.h>
#include <boost/noncopyable.hpp>
struct ServerFactory : boost::noncopyable {
static Server * CreateServer( IniFile & serverConfig ) {
int threads = omp_get_num_procs();
if( serverConfig.GetParameter("IP").empty() ) {
serverConfig.SetParameter("IP", "0.0.0.0");
}
if( serverConfig.GetParameter("Port").empty() ) {
serverConfig.SetParameter("Port", "5000");
}
if(
stringToInt(serverConfig.GetParameter("Threads")) >= 1 &&
stringToInt(serverConfig.GetParameter("Threads")) <= threads
) {
threads = stringToInt( serverConfig.GetParameter("Threads") );
}
SimpleLogger().Write() <<
"http 1.1 compression handled by zlib version " << zlibVersion();
Server * server = new Server(
serverConfig.GetParameter("IP"),
serverConfig.GetParameter("Port"),
threads
);
return server;
}
static Server * CreateServer(const char * iniFile) {
IniFile serverConfig(iniFile);
return CreateServer(serverConfig);
}
};
#endif /* SERVERFACTORY_H_ */
-1
View File
@@ -1 +0,0 @@
/osrm-component
-122
View File
@@ -1,122 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "../typedefs.h"
#include "../Algorithms/StronglyConnectedComponents.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/GraphLoader.h"
#include "../Util/IniFile.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include <boost/foreach.hpp>
#include <fstream>
#include <istream>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
std::vector<NodeInfo> internal_to_external_node_map;
std::vector<TurnRestriction> restrictions_vector;
std::vector<NodeID> bollard_node_IDs_vector;
std::vector<NodeID> traffic_light_node_IDs_vector;
int main (int argc, char * argv[]) {
LogPolicy::GetInstance().Unmute();
if(argc < 3) {
SimpleLogger().Write(logWARNING) <<
"usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
return -1;
}
SimpleLogger().Write() <<
"Using restrictions from file: " << argv[2];
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
if(!restriction_ifstream.good()) {
throw OSRMException("Could not access <osrm-restrictions> files");
}
uint32_t usable_restriction_count = 0;
restriction_ifstream.read(
(char*)&usable_restriction_count,
sizeof(uint32_t)
);
restrictions_vector.resize(usable_restriction_count);
restriction_ifstream.read(
(char *)&(restrictions_vector[0]),
usable_restriction_count*sizeof(TurnRestriction)
);
restriction_ifstream.close();
std::ifstream input_stream;
input_stream.open( argv[1], std::ifstream::in | std::ifstream::binary );
if (!input_stream.is_open()) {
throw OSRMException("Cannot open osrm file");
}
std::vector<ImportEdge> edge_list;
NodeID node_based_node_count = readBinaryOSRMGraphFromStream(
input_stream,
edge_list,
bollard_node_IDs_vector,
traffic_light_node_IDs_vector,
&internal_to_external_node_map,
restrictions_vector
);
input_stream.close();
SimpleLogger().Write() <<
restrictions_vector.size() << " restrictions, " <<
bollard_node_IDs_vector.size() << " bollard nodes, " <<
traffic_light_node_IDs_vector.size() << " traffic lights";
/***
* Building an edge-expanded graph from node-based input an turn restrictions
*/
SimpleLogger().Write() << "Starting SCC graph traversal";
TarjanSCC * tarjan = new TarjanSCC (
node_based_node_count,
edge_list,
bollard_node_IDs_vector,
traffic_light_node_IDs_vector,
restrictions_vector,
internal_to_external_node_map
);
std::vector<ImportEdge>().swap(edge_list);
tarjan->Run();
std::vector<TurnRestriction>().swap(restrictions_vector);
std::vector<NodeID>().swap(bollard_node_IDs_vector);
std::vector<NodeID>().swap(traffic_light_node_IDs_vector);
SimpleLogger().Write() << "finished component analysis";
return 0;
}
-93
View File
@@ -1,93 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
//Dude, real recursions on the OS stack? You must be brave...
void print_tree(boost::property_tree::ptree const& pt, const unsigned recursion_depth)
{
boost::property_tree::ptree::const_iterator end = pt.end();
for (boost::property_tree::ptree::const_iterator it = pt.begin(); it != end; ++it) {
for(unsigned i = 0; i < recursion_depth; ++i) {
std::cout << " " << std::flush;
}
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
print_tree(it->second, recursion_depth+1);
}
}
int main (int argc, char * argv[]) {
LogPolicy::GetInstance().Unmute();
try {
std::cout << "\n starting up engines, compile at "
<< __DATE__ << ", " __TIME__ << std::endl;
IniFile serverConfig((argc > 1 ? argv[1] : "server.ini"));
OSRM routing_machine((argc > 1 ? argv[1] : "server.ini"));
RouteParameters route_parameters;
route_parameters.zoomLevel = 18; //no generalization
route_parameters.printInstructions = true; //turn by turn instructions
route_parameters.alternateRoute = true; //get an alternate route, too
route_parameters.geometry = true; //retrieve geometry of route
route_parameters.compression = true; //polyline encoding
route_parameters.checkSum = UINT_MAX; //see wiki
route_parameters.service = "viaroute"; //that's routing
route_parameters.outputFormat = "json";
route_parameters.jsonpParameter = ""; //set for jsonp wrapping
route_parameters.language = ""; //unused atm
//route_parameters.hints.push_back(); // see wiki, saves I/O if done properly
FixedPointCoordinate start_coordinate(52.519930*COORDINATE_PRECISION,13.438640*COORDINATE_PRECISION);
FixedPointCoordinate target_coordinate(52.513191*COORDINATE_PRECISION,13.415852*COORDINATE_PRECISION);
route_parameters.coordinates.push_back(start_coordinate);
route_parameters.coordinates.push_back(target_coordinate);
http::Reply osrm_reply;
routing_machine.RunQuery(route_parameters, osrm_reply);
std::cout << osrm_reply.content << std::endl;
//attention: super-inefficient hack below:
std::stringstream ss;
ss << osrm_reply.content;
boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);
print_tree(pt, 0);
} catch (std::exception & e) {
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
return -1;
}
return 0;
}
-52
View File
@@ -1,52 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
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 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef AZIMUTH_H_
#define AZIMUTH_H_
#include <string>
struct Azimuth {
static std::string Get(const double heading) {
if(heading <= 202.5) {
if(heading >= 0 && heading <= 22.5)
return "N";
if(heading > 22.5 && heading <= 67.5)
return "NE";
if(heading > 67.5 && heading <= 112.5)
return "E";
if(heading > 112.5 && heading <= 157.5)
return "SE";
return "S";
}
if(heading > 202.5 && heading <= 247.5)
return "SW";
if(heading > 247.5 && heading <= 292.5)
return "W";
if(heading > 292.5 && heading <= 337.5)
return "NW";
return "N";
}
};
#endif /* AZIMUTH_H_ */

Some files were not shown because too many files have changed in this diff Show More