From 98783728666d0676b83223ea0a9dc3e7b0ccfabc Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 8 Jul 2011 17:27:16 +0000 Subject: [PATCH] Experimental plugin --- Plugins/ViaRoutePlugin.h | 284 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 Plugins/ViaRoutePlugin.h diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h new file mode 100644 index 000000000..f1e3e8acb --- /dev/null +++ b/Plugins/ViaRoutePlugin.h @@ -0,0 +1,284 @@ +/* + 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 +#include +#include +#include +#include + +#include "ObjectForPluginStruct.h" + +#include "BaseDescriptor.h" +#include "BasePlugin.h" +#include "RouteParameters.h" +#include "KMLDescriptor.h" +#include "JSONDescriptor.h" + +#include "../DataStructures/HashTable.h" +#include "../DataStructures/StaticGraph.h" +#include "../DataStructures/SearchEngine.h" + +#include "../Util/StringUtil.h" + +class ViaRoutePlugin : public BasePlugin { +private: + NodeInformationHelpDesk * nodeHelpDesk; + std::vector * names; + StaticGraph * graph; + HashTable descriptorTable; + std::string pluginDescriptorString; + + struct _ThreadData { + SearchEngine > * sEngine; + std::vector< _PathData > * path; + unsigned distanceOfSegment; + PhantomNodes phantomNodesOfSegment; + _ThreadData(SearchEngine > * s) : sEngine(s), distanceOfSegment(0) { + path = new std::vector< _PathData >(); + } + ~_ThreadData() { + delete path; + delete sEngine; + } + }; + + std::vector<_ThreadData *> threadData; + +public: + + ViaRoutePlugin(ObjectsForQueryStruct * objects, std::string psd = "viaroute") : pluginDescriptorString(psd) { + nodeHelpDesk = objects->nodeHelpDesk; + graph = objects->graph; + names = objects->names; + + unsigned maxThreads = omp_get_max_threads(); + for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) { + threadData.push_back( new _ThreadData( new SearchEngine >(graph, nodeHelpDesk, names)) ); + } + + descriptorTable.Set("", 0); //default descriptor + descriptorTable.Set("kml", 0); + descriptorTable.Set("json", 1); + } + + ~ViaRoutePlugin() { + for ( unsigned threadNum = 0; threadNum < threadData.size(); threadNum++ ) { + delete threadData[threadNum]; + } + } + + std::string GetDescriptor() { return pluginDescriptorString; } + std::string GetVersionString() { return std::string("0.3 (DL)"); } + void HandleRequest(RouteParameters routeParameters, http::Reply& reply) { + //check number of parameters + if(0 == routeParameters.options["start"].size() || 0 == routeParameters.options["dest"].size() ) { + reply = http::Reply::stockReply(http::Reply::badRequest); + return; + } + + //Get start and end Coordinate + std::string start = routeParameters.options["start"]; + std::string dest = routeParameters.options["dest"]; + + std::vector textCoord = split (start, ','); + + int lat1 = static_cast(100000.*atof(textCoord[0].c_str())); + int lon1 = static_cast(100000.*atof(textCoord[1].c_str())); + + textCoord = split (dest, ','); + + int lat2 = static_cast(100000.*atof(textCoord[0].c_str())); + int lon2 = static_cast(100000.*atof(textCoord[1].c_str())); + + _Coordinate startCoord(lat1, lon1); + _Coordinate targetCoord(lat2, lon2); + std::vector<_Coordinate> viaPointVector; + + if(false == checkCoord(startCoord) || false == checkCoord(targetCoord)) { + reply = http::Reply::stockReply(http::Reply::badRequest); + return; + } + viaPointVector.push_back(startCoord); + + std::cout << "[debug] number of vianodes: " << routeParameters.viaPoints.size() << std::endl; + for(unsigned i = 0; i < routeParameters.viaPoints.size(); i++) { + textCoord = split (routeParameters.viaPoints[i], ','); + if(textCoord.size() != 2) { + reply = http::Reply::stockReply(http::Reply::badRequest); + return; + } + int vialat = static_cast(100000.*atof(textCoord[0].c_str())); + int vialon = static_cast(100000.*atof(textCoord[1].c_str())); + std::cout << "[debug] via" << i << ": " << vialat << "," << vialon << std::endl; + _Coordinate viaCoord(vialat, vialon); + if(false == checkCoord(viaCoord)) { + reply = http::Reply::stockReply(http::Reply::badRequest); + return; + } + viaPointVector.push_back(viaCoord); + } + viaPointVector.push_back(targetCoord); + + + RawRouteData * rawRoute = new RawRouteData(viaPointVector.size()-1); + + unsigned distance = 0; + bool errorOccurredFlag = false; + double time = get_timestamp(); + +//#pragma omp parallel for reduction(+:distance) + for(unsigned i = 0; i < viaPointVector.size()-1; i++) { + PhantomNodes & segmentPhantomNodes = threadData[omp_get_thread_num()]->phantomNodesOfSegment; + std::vector< _PathData > path; + threadData[omp_get_thread_num()]->sEngine->FindRoutingStarts(viaPointVector[i], viaPointVector[i+1], &segmentPhantomNodes); + threadData[omp_get_thread_num()]->distanceOfSegment = threadData[omp_get_thread_num()]->sEngine->ComputeRoute(&segmentPhantomNodes, &path); + + if(UINT_MAX == threadData[omp_get_thread_num()]->distanceOfSegment) { + errorOccurredFlag = true; + } else { + distance += threadData[omp_get_thread_num()]->distanceOfSegment; + } + + std::cout << "Computing route segment " << i << std::endl; + + //put segments at correct position of routes raw data + rawRoute->segmentEndCoordinates[i] = (segmentPhantomNodes); + rawRoute->routeSegments[i] = path; + } + + double time2 = get_timestamp(); + std::cout << "Finished routing after " << (time2-time) << "s" << std::endl; + time = get_timestamp(); + + if(errorOccurredFlag) { + distance = UINT_MAX; + } else { + + + } + reply.status = http::Reply::ok; + + BaseDescriptor > > * desc; + std::string JSONParameter = routeParameters.options.Find("jsonp"); + if("" != JSONParameter) { + reply.content += JSONParameter; + reply.content += "(\n"; + } + + _DescriptorConfig descriptorConfig; + unsigned descriptorType = descriptorTable[routeParameters.options.Find("output")]; + unsigned short zoom = 18; + if(routeParameters.options.Find("z") != ""){ + zoom = atoi(routeParameters.options.Find("z").c_str()); + if(18 < zoom) + zoom = 18; + } + descriptorConfig.z = zoom; + if(routeParameters.options.Find("instructions") == "false") { + descriptorConfig.instructions = false; + } + if(routeParameters.options.Find("geometry") == "false" ) { + descriptorConfig.geometry = false; + } + if("cmp" == routeParameters.options.Find("geomformat") || "cmp6" == routeParameters.options.Find("geomformat") ) { + descriptorConfig.encodeGeometry = true; + } + + switch(descriptorType){ + case 0: + desc = new KMLDescriptor > >(); + + break; + case 1: + desc = new JSONDescriptor > >(); + + break; + default: + desc = new KMLDescriptor > >(); + + break; + } + PhantomNodes phantomNodes; + threadData[0]->sEngine->FindRoutingStarts(startCoord, targetCoord, &phantomNodes); + desc->SetConfig(descriptorConfig); + desc->Run(reply, rawRoute, &phantomNodes, threadData[0]->sEngine, distance); + if("" != JSONParameter) { + 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: + reply.headers[1].name = "Content-Type"; + reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8"; + reply.headers[2].name = "Content-Disposition"; + reply.headers[2].value = "attachment; filename=\"route.kml\""; + + break; + case 1: + if("" != JSONParameter){ + 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; + default: + reply.headers[1].name = "Content-Type"; + reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8"; + reply.headers[2].name = "Content-Disposition"; + reply.headers[2].value = "attachment; filename=\"route.kml\""; + + break; + } + + time2 = get_timestamp(); + std::cout << "Finished everything after " << (time2-time) << "s" << std::endl; + + + delete desc; + delete rawRoute; + return; + } +private: + inline bool checkCoord(const _Coordinate & c) { + if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) { + return false; + } + return true; + } +}; + + +#endif /* VIAROUTEPLUGIN_H_ */