Filtering of geometry details by zoom level
This commit is contained in:
parent
5642dc00e1
commit
9de3a5a586
@ -28,6 +28,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../DataStructures/ExtractorStructs.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../Util/StrIngUtil.h"
|
||||
|
||||
template<class SearchEngineT>
|
||||
@ -37,6 +38,7 @@ public:
|
||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() { }
|
||||
virtual void Run(http::Reply& reply, std::vector< _PathData > * path, PhantomNodes * phantomNodes, SearchEngineT * sEngine, unsigned distance) = 0;
|
||||
virtual void SetZoom(const unsigned short z) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -23,9 +23,20 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#ifndef JSONDESCRIPTOR_H_
|
||||
#define JSONDESCRIPTOR_H_
|
||||
|
||||
static double areaThresholds[19] = { 5000, 5000, 5000, 5000, 5000, 2500, 2000, 1500, 800, 400, 250, 150, 100, 75, 25, 20, 10, 5 };
|
||||
|
||||
template<class SearchEngineT, bool SimplifyRoute = false>
|
||||
class JSONDescriptor : public BaseDescriptor<SearchEngineT> {
|
||||
private:
|
||||
short zoom;
|
||||
public:
|
||||
JSONDescriptor() : zoom(18) {}
|
||||
void SetZoom(const unsigned short z) {
|
||||
if(z > 18)
|
||||
zoom = 18;
|
||||
zoom = z;
|
||||
}
|
||||
|
||||
void Run(http::Reply& reply, std::vector< _PathData > * path, PhantomNodes * phantomNodes, SearchEngineT * sEngine, unsigned distance) {
|
||||
string tmp;
|
||||
string routeGeometryString;
|
||||
@ -40,19 +51,22 @@ public:
|
||||
unsigned durationOfInstruction = 0;
|
||||
double lastAngle = 0.;
|
||||
|
||||
reply.content += ("{\n");
|
||||
reply.content += (" \"version\":0.3,\n");
|
||||
unsigned painted = 0;
|
||||
unsigned omitted = 0;
|
||||
|
||||
reply.content += ("{");
|
||||
reply.content += ("\"version\":0.3,");
|
||||
|
||||
if(distance != UINT_MAX) {
|
||||
reply.content += (" \"status\":0,\n");
|
||||
reply.content += (" \"status_message\":");
|
||||
reply.content += "\"Found route between points\",\n";
|
||||
reply.content += ("\"status\":0,");
|
||||
reply.content += ("\"status_message\":");
|
||||
reply.content += "\"Found route between points\",";
|
||||
unsigned streetID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2);
|
||||
startPointName = sEngine->GetNameForNameID(streetID);
|
||||
startPointName = sEngine->GetEscapedNameForNameID(streetID);
|
||||
streetID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2);
|
||||
endPointName = sEngine->GetNameForNameID(streetID);
|
||||
endPointName = sEngine->GetEscapedNameForNameID(streetID);
|
||||
|
||||
routeInstructionString += " [\"Head ";
|
||||
routeInstructionString += "[\"Head ";
|
||||
_Coordinate tmpCoord;
|
||||
if(path->size() > 0)
|
||||
sEngine->getNodeInfo(path->begin()->node, tmpCoord);
|
||||
@ -93,12 +107,12 @@ public:
|
||||
|
||||
//put start coord to linestring;
|
||||
convertLatLon(phantomNodes->startCoord.lat, tmp);
|
||||
routeGeometryString += " [";
|
||||
routeGeometryString += "[";
|
||||
routeGeometryString += tmp;
|
||||
routeGeometryString += ", ";
|
||||
convertLatLon(phantomNodes->startCoord.lon, tmp);
|
||||
routeGeometryString += tmp;
|
||||
routeGeometryString += "],\n";
|
||||
routeGeometryString += "],";
|
||||
position++;
|
||||
|
||||
_Coordinate previous(phantomNodes->startCoord.lat, phantomNodes->startCoord.lon);
|
||||
@ -132,16 +146,21 @@ public:
|
||||
durationOfInstruction += sEngine->GetWeightForOriginDestinationNodeID(it->node, (it+1)->node);
|
||||
}
|
||||
double angle = GetAngleBetweenTwoEdges(startOfSegment, current, next);
|
||||
if(178 > angle || 182 < angle || false == SimplifyRoute) {
|
||||
double area = fabs(0.5*( startOfSegment.lon*(current.lat - next.lat) + current.lon*(next.lat - startOfSegment.lat) + next.lon*(startOfSegment.lat - current.lat) ) );
|
||||
// std::cout << "Area for: " << area << std::endl;
|
||||
if(area > areaThresholds[zoom] || false == SimplifyRoute) {
|
||||
painted++;
|
||||
convertLatLon(current.lat, tmp);
|
||||
routeGeometryString += " [";
|
||||
routeGeometryString += "[";
|
||||
routeGeometryString += tmp;
|
||||
routeGeometryString += ", ";
|
||||
convertLatLon(current.lon, tmp);
|
||||
routeGeometryString += tmp;
|
||||
routeGeometryString += "],\n";
|
||||
routeGeometryString += "],";
|
||||
position++;
|
||||
startOfSegment = current;
|
||||
} else {
|
||||
omitted++;
|
||||
}
|
||||
if(nextID == nameID) {
|
||||
tempDist += ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon);
|
||||
@ -152,7 +171,7 @@ public:
|
||||
routeInstructionString += ",leave motorway and ";
|
||||
routeInstructionString += " on ";
|
||||
if(nameID != 0)
|
||||
routeInstructionString += sEngine->GetNameForNameID(nameID);
|
||||
routeInstructionString += sEngine->GetEscapedNameForNameID(nameID);
|
||||
routeInstructionString += "\",";
|
||||
distanceOfInstruction += ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon)+tempDist;
|
||||
entireDistance += distanceOfInstruction;
|
||||
@ -178,13 +197,13 @@ public:
|
||||
numberString.str("");
|
||||
numberString << fixed << setprecision(2) << lastAngle;
|
||||
routeInstructionString += numberString.str();
|
||||
routeInstructionString += "],\n";
|
||||
routeInstructionString += "],";
|
||||
|
||||
string lat; string lon;
|
||||
convertLatLon(lastPlace.lon, lon);
|
||||
convertLatLon(lastPlace.lat, lat);
|
||||
lastPlace = current;
|
||||
routeInstructionString += " [\"";
|
||||
routeInstructionString += "[\"";
|
||||
|
||||
if(angle > 160 && angle < 200) {
|
||||
routeInstructionString += /* " (" << angle << ")*/"Continue";
|
||||
@ -214,7 +233,7 @@ public:
|
||||
type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2);
|
||||
durationOfInstruction += sEngine->GetWeightForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2);
|
||||
routeInstructionString += " at ";
|
||||
routeInstructionString += sEngine->GetNameForNameID(nameID);
|
||||
routeInstructionString += sEngine->GetEscapedNameForNameID(nameID);
|
||||
routeInstructionString += "\",";
|
||||
distanceOfInstruction = ApproximateDistance(previous.lat, previous.lon, phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon) + tempDist;
|
||||
entireDistance += distanceOfInstruction;
|
||||
@ -239,58 +258,58 @@ public:
|
||||
numberString.str("");
|
||||
numberString << fixed << setprecision(2) << lastAngle;
|
||||
routeInstructionString += numberString.str();
|
||||
routeInstructionString += "]\n";
|
||||
routeInstructionString += "]";
|
||||
|
||||
string lat; string lon;
|
||||
|
||||
//put targetCoord to linestring
|
||||
convertLatLon(phantomNodes->targetCoord.lat, tmp);
|
||||
routeGeometryString += " [";
|
||||
routeGeometryString += "[";
|
||||
routeGeometryString += tmp;
|
||||
routeGeometryString += ", ";
|
||||
convertLatLon(phantomNodes->targetCoord.lon, tmp);
|
||||
routeGeometryString += tmp;
|
||||
routeGeometryString += "]\n";
|
||||
routeGeometryString += "]";
|
||||
position++;
|
||||
|
||||
//give complete distance in meters;
|
||||
ostringstream s;
|
||||
s << 10*(round(entireDistance/10.));
|
||||
routeSummaryString += " \"total_distance\":";
|
||||
routeSummaryString += "\"total_distance\":";
|
||||
routeSummaryString += s.str();
|
||||
routeSummaryString += ",\n \"total_time\":";
|
||||
routeSummaryString += ",\"total_time\":";
|
||||
//give travel time in minutes
|
||||
int travelTime = distance;
|
||||
s.str("");
|
||||
s << travelTime;
|
||||
routeSummaryString += s.str();
|
||||
routeSummaryString += ",\n \"start_point\":\"";
|
||||
routeSummaryString += ",\"start_point\":\"";
|
||||
routeSummaryString += startPointName;
|
||||
routeSummaryString += "\",\n \"end_point\":\"";
|
||||
routeSummaryString += "\",\"end_point\":\"";
|
||||
routeSummaryString += endPointName;
|
||||
routeSummaryString += "\"\n";
|
||||
routeSummaryString += "\"";
|
||||
} else {
|
||||
reply.content += (" \"status\":207,\n");
|
||||
reply.content += (" \"status_message\":");
|
||||
reply.content += "\"Cannot find route between points\",\n";
|
||||
routeSummaryString += " \"total_distance\":0";
|
||||
routeSummaryString += ",\n \"total_time\":0";
|
||||
routeSummaryString += ",\n \"start_point\":\"";
|
||||
routeSummaryString += "\",\n \"end_point\":\"";
|
||||
routeSummaryString += "\"\n";
|
||||
reply.content += ("\"status\":207,");
|
||||
reply.content += ("\"status_message\":");
|
||||
reply.content += "\"Cannot find route between points\",";
|
||||
routeSummaryString += "\"total_distance\":0";
|
||||
routeSummaryString += ",\"total_time\":0";
|
||||
routeSummaryString += ",\"start_point\":\"";
|
||||
routeSummaryString += "\",\"end_point\":\"";
|
||||
routeSummaryString += "\"";
|
||||
}
|
||||
reply.content += " \"route_summary\": {\n";
|
||||
reply.content += "\"route_summary\": {";
|
||||
reply.content += routeSummaryString;
|
||||
reply.content += " },\n";
|
||||
reply.content += " \"route_geometry\": [\n";
|
||||
reply.content += "},";
|
||||
reply.content += "\"route_geometry\": [";
|
||||
reply.content += routeGeometryString;
|
||||
reply.content += " ],\n";
|
||||
reply.content += " \"route_instructions\": [\n";
|
||||
reply.content += "],";
|
||||
reply.content += "\"route_instructions\": [";
|
||||
reply.content += routeInstructionString;
|
||||
reply.content += " ],\n";
|
||||
reply.content += " \"transactionId\": \"OSRM Routing Engine JSON Descriptor (beta)\"\n";
|
||||
reply.content += "],";
|
||||
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (beta)\"";
|
||||
reply.content += "}";
|
||||
//std::cout << "zoom: " << zoom << ", threshold: " << areaThresholds[zoom] << ", painted: " << painted << ", omitted: " << omitted << std::endl;
|
||||
}
|
||||
private:
|
||||
};
|
||||
#endif /* JSONDESCRIPTOR_H_ */
|
||||
|
@ -24,6 +24,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
template<class SearchEngineT, bool SimplifyRoute = false>
|
||||
class KMLDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||
public:
|
||||
void SetZoom(const unsigned short z) { }
|
||||
void Run(http::Reply& reply, std::vector< _PathData > * path, PhantomNodes * phantomNodes, SearchEngineT * sEngine, unsigned distance) {
|
||||
string tmp;
|
||||
string lineString;
|
||||
|
@ -25,73 +25,125 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "RouteParameters.h"
|
||||
|
||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
||||
#include "../DataStructures/HashTable.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(std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath) {
|
||||
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str());
|
||||
ifstream nodesInStream(nodesPath.c_str(), ios::binary);
|
||||
nodeHelpDesk->initNNGrid(nodesInStream);
|
||||
}
|
||||
~NearestPlugin() {
|
||||
delete nodeHelpDesk;
|
||||
}
|
||||
std::string GetDescriptor() { return std::string("nearest"); }
|
||||
std::string GetVersionString() { return std::string("0.3 (DL)"); }
|
||||
void HandleRequest(RouteParameters routeParameters, http::Reply& reply) {
|
||||
//check number of parameters
|
||||
if(routeParameters.parameters.size() != 2) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
NearestPlugin(std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath) {
|
||||
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str());
|
||||
ifstream nodesInStream(nodesPath.c_str(), ios::binary);
|
||||
nodeHelpDesk->initNNGrid(nodesInStream);
|
||||
descriptorTable.Set("", 0); //default descriptor
|
||||
descriptorTable.Set("kml", 0);
|
||||
descriptorTable.Set("json", 1);
|
||||
}
|
||||
~NearestPlugin() {
|
||||
delete nodeHelpDesk;
|
||||
}
|
||||
std::string GetDescriptor() { return std::string("nearest"); }
|
||||
std::string GetVersionString() { return std::string("0.3 (DL)"); }
|
||||
void HandleRequest(RouteParameters routeParameters, http::Reply& reply) {
|
||||
//check number of parameters
|
||||
if(routeParameters.parameters.size() != 2) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
int lat = static_cast<int>(100000.*atof(routeParameters.parameters[0].c_str()));
|
||||
int lon = static_cast<int>(100000.*atof(routeParameters.parameters[1].c_str()));
|
||||
int lat = static_cast<int>(100000.*atof(routeParameters.parameters[0].c_str()));
|
||||
int lon = static_cast<int>(100000.*atof(routeParameters.parameters[1].c_str()));
|
||||
|
||||
if(lat>90*100000 || lat <-90*100000 || lon>180*100000 || lon <-180*100000) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
//query to helpdesk
|
||||
_Coordinate result;
|
||||
nodeHelpDesk->FindNearestPointOnEdge(_Coordinate(lat, lon), result);
|
||||
if(lat>90*100000 || lat <-90*100000 || lon>180*100000 || lon <-180*100000) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
//query to helpdesk
|
||||
_Coordinate result;
|
||||
nodeHelpDesk->FindNearestPointOnEdge(_Coordinate(lat, lon), result);
|
||||
unsigned descriptorType = descriptorTable[routeParameters.options.Find("output")];
|
||||
std::stringstream out1;
|
||||
std::stringstream out2;
|
||||
std::string tmp;
|
||||
std::string JSONParameter;
|
||||
switch(descriptorType){
|
||||
case 1:
|
||||
//json
|
||||
|
||||
//Write to stream
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
|
||||
reply.content.append("<Placemark>");
|
||||
JSONParameter = routeParameters.options.Find("jsonp");
|
||||
if("" != JSONParameter) {
|
||||
reply.content += JSONParameter;
|
||||
reply.content += "(\n";
|
||||
}
|
||||
|
||||
std::stringstream out1;
|
||||
out1 << setprecision(10);
|
||||
out1 << "<name>Nearest Place in map to " << lat/100000. << "," << lon/100000. << "</name>";
|
||||
reply.content.append(out1.str());
|
||||
reply.content.append("<Point>");
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content += ("{");
|
||||
reply.content += ("\"version\":0.3,");
|
||||
reply.content += ("\"status\":0,");
|
||||
reply.content += ("\"status_message\":");
|
||||
out1 << setprecision(10);
|
||||
out1 << "\"Nearest Place in map to " << lat/100000. << "," << lon/100000. << "\",";
|
||||
reply.content.append(out1.str());
|
||||
reply.content += ("\"coordinate\": ");
|
||||
out2 << setprecision(10);
|
||||
out2 << "[" << result.lat / 100000. << "," << result.lon / 100000. << "]";
|
||||
reply.content.append(out2.str());
|
||||
|
||||
std::stringstream out2;
|
||||
out2 << setprecision(10);
|
||||
out2 << "<coordinates>" << result.lon / 100000. << "," << result.lat / 100000. << "</coordinates>";
|
||||
reply.content.append(out2.str());
|
||||
reply.content.append("</Point>");
|
||||
reply.content.append("</Placemark>");
|
||||
reply.content.append("</kml>");
|
||||
reply.content += ("}");
|
||||
reply.headers.resize(3);
|
||||
reply.headers[0].name = "Content-Length";
|
||||
intToString(reply.content.size(), tmp);
|
||||
reply.headers[0].value = tmp;if("" != JSONParameter) {
|
||||
reply.content += ")\n";
|
||||
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.resize(3);
|
||||
reply.headers[0].name = "Content-Length";
|
||||
reply.headers[0].value = boost::lexical_cast<std::string>(reply.content.size());
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/vnd.google-earth.kml+xml";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"placemark.kml\"";
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
//Write to stream
|
||||
reply.content.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
|
||||
reply.content.append("<Placemark>");
|
||||
|
||||
|
||||
out1 << setprecision(10);
|
||||
out1 << "<name>Nearest Place in map to " << lat/100000. << "," << lon/100000. << "</name>";
|
||||
reply.content.append(out1.str());
|
||||
reply.content.append("<Point>");
|
||||
|
||||
out2 << setprecision(10);
|
||||
out2 << "<coordinates>" << result.lon / 100000. << "," << result.lat / 100000. << "</coordinates>";
|
||||
reply.content.append(out2.str());
|
||||
reply.content.append("</Point>");
|
||||
reply.content.append("</Placemark>");
|
||||
reply.content.append("</kml>");
|
||||
|
||||
reply.headers.resize(3);
|
||||
reply.headers[0].name = "Content-Length";
|
||||
reply.headers[0].value = boost::lexical_cast<std::string>(reply.content.size());
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/vnd.google-earth.kml+xml";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"placemark.kml\"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
NodeInformationHelpDesk * nodeHelpDesk;
|
||||
NodeInformationHelpDesk * nodeHelpDesk;
|
||||
HashTable<std::string, unsigned> descriptorTable;
|
||||
};
|
||||
|
||||
#endif /* NearestPlugin_H_ */
|
||||
|
@ -21,6 +21,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#ifndef ROUTEPLUGIN_H_
|
||||
#define ROUTEPLUGIN_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@ -127,6 +128,12 @@ public:
|
||||
}
|
||||
unsigned descriptorType = descriptorTable[routeParameters.options.Find("output")];
|
||||
const bool simplifiedRoute = (routeParameters.options.Find("simplified") == "yes");
|
||||
unsigned short zoom;
|
||||
if(routeParameters.options.Find("z") != ""){
|
||||
zoom = atoi(routeParameters.options.Find("z").c_str());
|
||||
if(18 < zoom)
|
||||
zoom = 18;
|
||||
}
|
||||
//todo: put options in a seperate struct and pass it to the descriptor
|
||||
switch(descriptorType){
|
||||
case 0:
|
||||
@ -148,7 +155,7 @@ public:
|
||||
desc = new KMLDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> >, false >();
|
||||
break;
|
||||
}
|
||||
|
||||
desc->SetZoom(zoom);
|
||||
desc->Run(reply, path, phantomNodes, sEngine, distance);
|
||||
if("" != JSONParameter) {
|
||||
reply.content += ")\n";
|
||||
@ -175,7 +182,7 @@ public:
|
||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
||||
} else {
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/json";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user