First working edge based version. Still missing: GPX export; Via Points;

origin,destination on same edge, descriptions
This commit is contained in:
DennisOSRM
2011-11-14 19:36:31 +01:00
parent 34e4ead885
commit 97afa231ca
24 changed files with 512 additions and 1248 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ public:
if( ! path.size() )
continue;
for(vector< _PathData >::const_iterator it = path.begin(); it != path.end(); it++) {
sEngine.getCoordinatesForNodeID(it->node, current);
sEngine.GetCoordinatesForNodeID(it->node, current);
convertInternalLatLonToString(current.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
+8 -131
View File
@@ -21,6 +21,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include <boost/foreach.hpp>
#include "BaseDescriptor.h"
#include "../DataStructures/PolylineCompressor.h"
@@ -48,143 +50,18 @@ public:
//Put first segment of route into geometry
polyline.push_back(phantomNodes.startPhantom.location);
descriptorState.geometryCounter++;
descriptorState.startOfSegmentCoordinate = phantomNodes.startPhantom.location;
//Generate initial instruction for start of route (order of NodeIDs does not matter, its the same name anyway)
summary.startName = sEngine.GetEscapedNameForOriginDestinationNodeID(phantomNodes.startPhantom.startNode, phantomNodes.startPhantom.targetNode);
descriptorState.lastNameID = sEngine.GetNameIDForOriginDestinationNodeID(phantomNodes.startPhantom.startNode, phantomNodes.startPhantom.targetNode);
//If we have a route, i.e. start and dest not on same edge, than get it
if(rawRoute.routeSegments[0].size() > 0)
sEngine.getCoordinatesForNodeID(rawRoute.routeSegments[0].begin()->node, descriptorState.tmpCoord);
else
descriptorState.tmpCoord = phantomNodes.targetPhantom.location;
descriptorState.previousCoordinate = phantomNodes.startPhantom.location;
descriptorState.currentCoordinate = descriptorState.tmpCoord;
descriptorState.distanceOfInstruction += ApproximateDistance(descriptorState.previousCoordinate, descriptorState.currentCoordinate);
if(config.instructions) {
//Get Heading
double angle = GetAngleBetweenTwoEdges(_Coordinate(phantomNodes.startPhantom.location.lat, phantomNodes.startPhantom.location.lon), descriptorState.tmpCoord, _Coordinate(descriptorState.tmpCoord.lat, descriptorState.tmpCoord.lon-1000));
getDirectionOfInstruction(angle, directionOfInstruction);
appendInstructionNameToString(summary.startName, directionOfInstruction.direction, descriptorState.routeInstructionString, true);
}
NodeID lastNodeID = UINT_MAX;
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
if(path.empty())
continue;
if ( UINT_MAX == lastNodeID) {
lastNodeID = (phantomNodes.startPhantom.startNode == (*path.begin()).node ? phantomNodes.startPhantom.targetNode : phantomNodes.startPhantom.startNode);
}
//Check, if there is overlap between current and previous route segment
//if not, than we are fine and can route over this edge without paying any special attention.
if(lastNodeID == (*path.begin()).node) {
// appendCoordinateToString(descriptorState.currentCoordinate, descriptorState.routeGeometryString);
polyline.push_back(descriptorState.currentCoordinate);
descriptorState.geometryCounter++;
lastNodeID = (lastNodeID == rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode ? rawRoute.segmentEndCoordinates[segmentIdx].targetPhantom.startNode : rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode);
//output of the via nodes coordinates
polyline.push_back(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location);
descriptorState.geometryCounter++;
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode, rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.targetNode);
//Make a special announement to do a U-Turn.
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.routeInstructionString += ",";
descriptorState.distanceOfInstruction = ApproximateDistance(descriptorState.currentCoordinate, rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location);
getTurnDirectionOfInstruction(descriptorState.GetAngleBetweenCoordinates(), tmp);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.routeInstructionString += ",";
tmp = "U-turn at via point";
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
double tmpDistance = descriptorState.distanceOfInstruction;
descriptorState.SetStartOfSegment(); //Set start of segment but save distance information.
descriptorState.distanceOfInstruction = tmpDistance;
} else if(segmentIdx > 0) { //We are going straight through an edge which is carrying the via point.
assert(segmentIdx != 0);
//routeInstructionString += "reaching via node: ";
descriptorState.nextCoordinate = rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location;
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode, rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.targetNode);
polyline.push_back(descriptorState.currentCoordinate);
descriptorState.geometryCounter++;
polyline.push_back(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location);
descriptorState.geometryCounter++;
if(config.instructions) {
double turnAngle = descriptorState.GetAngleBetweenCoordinates();
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.SetStartOfSegment();
descriptorState.routeInstructionString += ",";
getTurnDirectionOfInstruction(turnAngle, tmp);
tmp += " and reach via point";
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
//instruction to continue on the segment
appendInstructionLengthToString(ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate), descriptorState.routeInstructionString);
descriptorState.entireDistance += ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate);
descriptorState.routeInstructionString += ",";
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), "Continue ", descriptorState.routeInstructionString);
//note the new segment starting coordinates
descriptorState.SetStartOfSegment();
descriptorState.previousCoordinate = descriptorState.currentCoordinate;
descriptorState.currentCoordinate = descriptorState.nextCoordinate;
}
}
for(vector< _PathData >::const_iterator it = path.begin(); it != path.end(); it++) {
sEngine.getCoordinatesForNodeID(it->node, descriptorState.nextCoordinate);
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(lastNodeID, it->node);
double area = fabs(0.5*( descriptorState.startOfSegmentCoordinate.lon*(descriptorState.nextCoordinate.lat - descriptorState.currentCoordinate.lat) + descriptorState.nextCoordinate.lon*(descriptorState.currentCoordinate.lat - descriptorState.startOfSegmentCoordinate.lat) + descriptorState.currentCoordinate.lon*(descriptorState.startOfSegmentCoordinate.lat - descriptorState.nextCoordinate.lat) ) );
//if route is generalization does not skip this point, add it to description
if( config.z == 19 || area >= areaThresholds[config.z] || (false == descriptorState.CurrentAndPreviousNameIDsEqual()) ) {
//mark the beginning of the segment thats announced
// appendCoordinateToString(descriptorState.currentCoordinate, descriptorState.routeGeometryString);
polyline.push_back(descriptorState.currentCoordinate);
descriptorState.geometryCounter++;
if( ( false == descriptorState.CurrentAndPreviousNameIDsEqual() ) && config.instructions) {
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.routeInstructionString += ",";
getTurnDirectionOfInstruction(descriptorState.GetAngleBetweenCoordinates(), tmp);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
//note the new segment starting coordinates
descriptorState.SetStartOfSegment();
}
}
descriptorState.distanceOfInstruction += ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate);
lastNodeID = it->node;
if(it != path.begin()) {
descriptorState.previousCoordinate = descriptorState.currentCoordinate;
descriptorState.currentCoordinate = descriptorState.nextCoordinate;
}
BOOST_FOREACH(_PathData pathData, path) {
_Coordinate current;
sEngine.GetCoordinatesForNodeID(pathData.node, current);
polyline.push_back(current);
// INFO(pathData.node << " at " << current.lat << "," << current.lon);
//INFO("routed over node: " << pathData.node);
}
}
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(phantomNodes.targetPhantom.startNode, phantomNodes.targetPhantom.targetNode);
descriptorState.nextCoordinate = phantomNodes.targetPhantom.location;
polyline.push_back(descriptorState.currentCoordinate);
descriptorState.geometryCounter++;
if((false == descriptorState.CurrentAndPreviousNameIDsEqual()) && config.instructions) {
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.routeInstructionString += ",";
getTurnDirectionOfInstruction(descriptorState.GetAngleBetweenCoordinates(), tmp);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
descriptorState.distanceOfInstruction = 0;
descriptorState.SetStartOfSegment();
}
summary.destName = sEngine.GetEscapedNameForNameID(descriptorState.currentNameID);
descriptorState.distanceOfInstruction += ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate);
polyline.push_back(phantomNodes.targetPhantom.location);
descriptorState.geometryCounter++;
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
summary.BuildDurationAndLengthStrings(descriptorState.entireDistance, distance);
} else {
//no route found
reply.content += "207,"
-249
View File
@@ -1,249 +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 KML_DESCRIPTOR_H_
#define KML_DESCRIPTOR_H_
#include "BaseDescriptor.h"
template<class SearchEngineT>
class KMLDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
RouteSummary summary;
DirectionOfInstruction directionOfInstruction;
DescriptorState descriptorState;
std::string tmp;
public:
KMLDescriptor() {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
WriteHeaderToOutput(reply.content);
//We do not need to do much, if there is no route ;-)
if(distance != UINT_MAX && rawRoute.routeSegments.size() > 0) {
//Put first segment of route into geometry
appendCoordinateToString(phantomNodes.startPhantom.location, descriptorState.routeGeometryString);
descriptorState.startOfSegmentCoordinate = phantomNodes.startPhantom.location;
//Generate initial instruction for start of route (order of NodeIDs does not matter, its the same name anyway)
summary.startName = sEngine.GetEscapedNameForOriginDestinationNodeID(phantomNodes.startPhantom.startNode, phantomNodes.startPhantom.targetNode);
descriptorState.lastNameID = sEngine.GetNameIDForOriginDestinationNodeID(phantomNodes.startPhantom.startNode, phantomNodes.startPhantom.targetNode);
//If we have a route, i.e. start and dest not on same edge, than get it
if(rawRoute.routeSegments[0].size() > 0)
sEngine.getCoordinatesForNodeID(rawRoute.routeSegments[0].begin()->node, descriptorState.tmpCoord);
else
descriptorState.tmpCoord = phantomNodes.targetPhantom.location;
descriptorState.previousCoordinate = phantomNodes.startPhantom.location;
descriptorState.currentCoordinate = descriptorState.tmpCoord;
descriptorState.distanceOfInstruction += ApproximateDistance(descriptorState.previousCoordinate, descriptorState.currentCoordinate);
if(config.instructions) {
//Get Heading
double angle = GetAngleBetweenTwoEdges(_Coordinate(phantomNodes.startPhantom.location.lat, phantomNodes.startPhantom.location.lon), descriptorState.tmpCoord, _Coordinate(descriptorState.tmpCoord.lat, descriptorState.tmpCoord.lon-1000));
getDirectionOfInstruction(angle, directionOfInstruction);
appendInstructionNameToString(summary.startName, directionOfInstruction.direction, descriptorState.routeInstructionString, true);
}
NodeID lastNodeID = UINT_MAX;
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
if( ! path.size() )
continue;
if ( UINT_MAX == lastNodeID) {
lastNodeID = (phantomNodes.startPhantom.startNode == (*path.begin()).node ? phantomNodes.startPhantom.targetNode : phantomNodes.startPhantom.startNode);
}
//Check, if there is overlap between current and previous route segment
//if not, than we are fine and can route over this edge without paying any special attention.
if(lastNodeID == (*path.begin()).node) {
appendCoordinateToString(descriptorState.currentCoordinate, descriptorState.routeGeometryString);
lastNodeID = (lastNodeID == rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode ? rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.targetNode : rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode);
//output of the via nodes coordinates
appendCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, descriptorState.routeGeometryString);
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode, rawRoute.segmentEndCoordinates[segmentIdx].targetPhantom.startNode);
//Make a special announement to do a U-Turn.
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.distanceOfInstruction = ApproximateDistance(descriptorState.currentCoordinate, rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location);
getTurnDirectionOfInstruction(descriptorState.GetAngleBetweenCoordinates(), tmp);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
tmp = "U-turn at via point";
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
double tmpDistance = descriptorState.distanceOfInstruction;
descriptorState.SetStartOfSegment(); //Set start of segment but save distance information.
descriptorState.distanceOfInstruction = tmpDistance;
} else if(segmentIdx > 0) { //We are going straight through an edge which is carrying the via point.
assert(segmentIdx != 0);
//routeInstructionString += "\nreaching via node: \n";
descriptorState.nextCoordinate = rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location;
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.startNode, rawRoute.segmentEndCoordinates[segmentIdx].targetPhantom.startNode);
appendCoordinateToString(descriptorState.currentCoordinate, descriptorState.routeGeometryString);
appendCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, descriptorState.routeGeometryString);
if(config.instructions) {
double turnAngle = descriptorState.GetAngleBetweenCoordinates();
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
getTurnDirectionOfInstruction(turnAngle, tmp);
tmp += " and reach via point";
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
//instruction to continue on the segment
appendInstructionLengthToString(ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate), descriptorState.routeInstructionString);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), "Continue on", descriptorState.routeInstructionString);
//note the new segment starting coordinates
descriptorState.SetStartOfSegment();
descriptorState.previousCoordinate = descriptorState.currentCoordinate;
descriptorState.currentCoordinate = descriptorState.nextCoordinate;
} else {
assert(false);
}
}
for(vector< _PathData >::const_iterator it = path.begin(); it != path.end(); it++) {
sEngine.getCoordinatesForNodeID(it->node, descriptorState.nextCoordinate);
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(lastNodeID, it->node);
double area = fabs(0.5*( descriptorState.startOfSegmentCoordinate.lon*(descriptorState.nextCoordinate.lat - descriptorState.currentCoordinate.lat) + descriptorState.nextCoordinate.lon*(descriptorState.currentCoordinate.lat - descriptorState.startOfSegmentCoordinate.lat) + descriptorState.currentCoordinate.lon*(descriptorState.startOfSegmentCoordinate.lat - descriptorState.nextCoordinate.lat) ) );
//if route is generalization does not skip this point, add it to description
if( it==path.end()-1 || config.z == 19 || area >= areaThresholds[config.z] || (false == descriptorState.CurrentAndPreviousNameIDsEqual()) ) {
//mark the beginning of the segment thats announced
appendCoordinateToString(descriptorState.currentCoordinate, descriptorState.routeGeometryString);
if( ( false == descriptorState.CurrentAndPreviousNameIDsEqual() ) && config.instructions) {
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
getTurnDirectionOfInstruction(descriptorState.GetAngleBetweenCoordinates(), tmp);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
//note the new segment starting coordinates
descriptorState.SetStartOfSegment();
}
}
descriptorState.distanceOfInstruction += ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate);
lastNodeID = it->node;
if(it != path.begin()) {
descriptorState.previousCoordinate = descriptorState.currentCoordinate;
descriptorState.currentCoordinate = descriptorState.nextCoordinate;
}
}
}
descriptorState.currentNameID = sEngine.GetNameIDForOriginDestinationNodeID(phantomNodes.targetPhantom.startNode, phantomNodes.startPhantom.targetNode);
descriptorState.nextCoordinate = phantomNodes.targetPhantom.location;
appendCoordinateToString(descriptorState.currentCoordinate, descriptorState.routeGeometryString);
if((false == descriptorState.CurrentAndPreviousNameIDsEqual()) && config.instructions) {
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
getTurnDirectionOfInstruction(descriptorState.GetAngleBetweenCoordinates(), tmp);
appendInstructionNameToString(sEngine.GetEscapedNameForNameID(descriptorState.currentNameID), tmp, descriptorState.routeInstructionString);
descriptorState.distanceOfInstruction = 0;
}
summary.destName = sEngine.GetEscapedNameForNameID(descriptorState.currentNameID);
descriptorState.distanceOfInstruction += ApproximateDistance(descriptorState.currentCoordinate, descriptorState.nextCoordinate);
appendCoordinateToString(phantomNodes.targetPhantom.location, descriptorState.routeGeometryString);
appendInstructionLengthToString(descriptorState.distanceOfInstruction, descriptorState.routeInstructionString);
descriptorState.SetStartOfSegment();
//compute distance/duration for route summary
ostringstream s;
s << 10*(round(descriptorState.entireDistance/10.));
summary.lengthString = s.str();
int travelTime = 60*(distance/60.) + 1;
s.str("");
s << travelTime;
summary.durationString = s.str();
//writing summary of route to reply
reply.content += "<Placemark><name><![CDATA[Route from ";
reply.content += summary.startName;
reply.content += " to ";
reply.content += summary.destName;
reply.content += "]]></name><description><![CDATA[Distance: ";
reply.content += summary.lengthString;
reply.content += "&#160;m (approx. ";
reply.content += summary.durationString;
reply.content += " minutes)]]></description>\n";
reply.content += "<GeometryCollection><LineString><coordinates>";
if(config.geometry)
reply.content += descriptorState.routeGeometryString;
reply.content += "</coordinates></LineString></GeometryCollection>";
reply.content += "</Placemark>";
//list all viapoints so that the client may display it
std::cout << "number of segment endpoints in route: " << rawRoute.segmentEndCoordinates.size() << std::endl;
for(unsigned segmentIdx = 1; (true == config.geometry) && (segmentIdx < rawRoute.segmentEndCoordinates.size()); segmentIdx++) {
reply.content += "<Placemark>";
reply.content += "<name>Via Point 1</name>";
reply.content += "<Point>";
reply.content += "<coordinates>";
appendCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, reply.content);
reply.content += "</coordinates>";
reply.content += "</Point>";
reply.content += "</Placemark>";
}
}
reply.content += descriptorState.routeInstructionString;
reply.content += "</Document>\n</kml>";
std::cout << descriptorState.routeInstructionString << std::endl;
}
private:
void appendCoordinateToString(const _Coordinate coordinate, std::string & output) {
if(config.geometry) {
convertInternalCoordinateToString(coordinate, tmp);
output += tmp;
}
}
void appendInstructionNameToString(const std::string & nameOfStreet, const std::string & instructionOrDirection, std::string &output, bool firstAdvice = false) {
if(config.instructions) {
output += "<placemark><name><![CDATA[";
if(firstAdvice) {
output += "Head on ";
output += nameOfStreet;
output += " direction ";
output += instructionOrDirection;
} else {
output += instructionOrDirection;
output += " on ";
output += nameOfStreet;
}
output += "]]></name>";
}
}
void appendInstructionLengthToString(unsigned length, std::string &output) {
if(config.instructions){
output += "\n\t<description>drive for ";
intToString(10*(round(length/10.)), tmp);
output += tmp;
output += "m</description></placemark>";
output += "\n";
}
}
void WriteHeaderToOutput(std::string & output) {
output = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>\n");
}
};
#endif /* KML_DESCRIPTOR_H_ */
+11 -9
View File
@@ -28,28 +28,30 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "../DataStructures/StaticGraph.h"
#include "../Util/GraphLoader.h"
typedef StaticGraph<EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
struct ObjectsForQueryStruct {
typedef StaticGraph<EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> * names;
QueryGraph * graph;
ObjectsForQueryStruct(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string namesPath, std::string psd = "route") {
std::cout << "[objects] loading query data structures ..." << std::flush;
//Init nearest neighbor data structure
ifstream nodesInStream(nodesPath.c_str(), ios::binary);
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str());
nodeHelpDesk->initNNGrid(nodesInStream);
ifstream hsgrInStream(hsgrPath.c_str(), ios::binary);
//Deserialize road network graph
std::vector< InputEdge> edgeList;
readHSGRFromStream(hsgrInStream, edgeList);
graph = new QueryGraph(nodeHelpDesk->getNumberOfNodes()-1, edgeList);
const int n = readHSGRFromStream(hsgrInStream, edgeList);
INFO("Graph has " << n << " nodes");
graph = new QueryGraph(n, edgeList);
std::vector< InputEdge >().swap( edgeList ); //free memory
//Init nearest neighbor data structure
ifstream nodesInStream(nodesPath.c_str(), ios::binary);
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n);
nodeHelpDesk->initNNGrid(nodesInStream);
//deserialize street name list
ifstream namesInStream(namesPath.c_str(), ios::binary);
unsigned size(0);
-209
View File
@@ -1,209 +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 ROUTEPLUGIN_H_
#define ROUTEPLUGIN_H_
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include "ObjectForPluginStruct.h"
#include "BaseDescriptor.h"
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "KMLDescriptor.h"
#include "JSONDescriptor.h"
#include "GPXDescriptor.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/StaticGraph.h"
#include "../DataStructures/SearchEngine.h"
#include "../Util/StringUtil.h"
class RoutePlugin : public BasePlugin {
public:
RoutePlugin(ObjectsForQueryStruct * objects, std::string psd = "route") : pluginDescriptorString(psd) {
nodeHelpDesk = objects->nodeHelpDesk;
graph = objects->graph;
names = objects->names;
sEngine = new SearchEngine<EdgeData, StaticGraph<EdgeData> >(graph, nodeHelpDesk, names);
descriptorTable.Set("", 0); //default descriptor
descriptorTable.Set("kml", 0);
descriptorTable.Set("json", 1);
descriptorTable.Set("gpx", 2);
}
virtual ~RoutePlugin() {
DELETE(sEngine);
}
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(routeParameters.parameters.size() != 4) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
int lat1 = static_cast<int>(100000.*atof(routeParameters.parameters[0].c_str()));
int lon1 = static_cast<int>(100000.*atof(routeParameters.parameters[1].c_str()));
int lat2 = static_cast<int>(100000.*atof(routeParameters.parameters[2].c_str()));
int lon2 = static_cast<int>(100000.*atof(routeParameters.parameters[3].c_str()));
_DescriptorConfig descriptorConfig;
if("false" == routeParameters.options["geometry"]) {
descriptorConfig.geometry = false;
}
if(lat1>90*100000 || lat1 <-90*100000 || lon1>180*100000 || lon1 <-180*100000) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
if(lat2>90*100000 || lat2 <-90*100000 || lon2>180*100000 || lon2 <-180*100000) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
_Coordinate startCoord(lat1, lon1);
_Coordinate targetCoord(lat2, lon2);
vector< _PathData > path;
RawRouteData rawRoute;
PhantomNodes phantomNodes;
sEngine->FindRoutingStarts(startCoord, targetCoord, phantomNodes);
unsigned int distance = sEngine->ComputeRoute(phantomNodes, path);
rawRoute.routeSegments.push_back(path);
reply.status = http::Reply::ok;
BaseDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > > * desc;
std::string JSONParameter = routeParameters.options.Find("jsonp");
if("" != JSONParameter) {
reply.content += JSONParameter;
reply.content += "(\n";
}
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<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
case 1:
desc = new JSONDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
case 2:
desc = new GPXDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
default:
desc = new KMLDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
}
desc->SetConfig(descriptorConfig);
desc->Run(reply, rawRoute, phantomNodes, *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;
case 2:
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:
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;
}
DELETE( desc );
return;
}
private:
NodeInformationHelpDesk * nodeHelpDesk;
SearchEngine<EdgeData, StaticGraph<EdgeData> > *sEngine;
std::vector<std::string> * names;
StaticGraph<EdgeData> * graph;
HashTable<std::string, unsigned> descriptorTable;
std::string pluginDescriptorString;
};
#endif /* ROUTEPLUGIN_H_ */
+8 -10
View File
@@ -33,7 +33,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "GPXDescriptor.h"
#include "KMLDescriptor.h"
#include "JSONDescriptor.h"
#include "../DataStructures/HashTable.h"
@@ -103,7 +102,7 @@ public:
}
rawRoute.rawViaNodeCoordinates.push_back(startCoord);
// std::cout << "[debug] number of vianodes: " << routeParameters.viaPoints.size() << std::endl;
INFO("[debug] number of vianodes: " << routeParameters.viaPoints.size());
for(unsigned i = 0; i < routeParameters.viaPoints.size(); i++) {
textCoord = split (routeParameters.viaPoints[i], ',');
if(textCoord.size() != 2) {
@@ -112,7 +111,7 @@ public:
}
int vialat = static_cast<int>(100000.*atof(textCoord[0].c_str()));
int vialon = static_cast<int>(100000.*atof(textCoord[1].c_str()));
// std::cout << "[debug] via" << i << ": " << vialat << "," << vialon << std::endl;
INFO("[debug] via" << i << ": " << vialat << "," << vialon);
_Coordinate viaCoord(vialat, vialon);
if(false == checkCoord(viaCoord)) {
reply = http::Reply::stockReply(http::Reply::badRequest);
@@ -138,12 +137,13 @@ public:
PhantomNodes segmentPhantomNodes;
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
INFO(segmentPhantomNodes);
std::vector< _PathData > path;
unsigned distanceOfSegment = searchEngine->ComputeRoute(segmentPhantomNodes, path);
if(UINT_MAX == distanceOfSegment ) {
errorOccurredFlag = true;
// cout << "Error occurred, path not found" << endl;
INFO( "Error occurred, path not found" );
distance = UINT_MAX;
break;
} else {
@@ -155,6 +155,8 @@ public:
rawRoute.routeSegments[i] = path;
}
INFO("Found path of length: " << distance);
reply.status = http::Reply::ok;
BaseDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > > * desc;
@@ -185,19 +187,15 @@ public:
switch(descriptorType){
case 0:
desc = new KMLDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
case 1:
desc = new JSONDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
case 2:
case 1:
desc = new GPXDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
default:
desc = new KMLDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
desc = new JSONDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > >();
break;
}