diff --git a/Plugins/GPXDescriptor.h b/Plugins/GPXDescriptor.h new file mode 100644 index 000000000..c438b6fb4 --- /dev/null +++ b/Plugins/GPXDescriptor.h @@ -0,0 +1,238 @@ +/* + 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" + +template +class GPXDescriptor : public BaseDescriptor{ +private: + DescriptorConfig config; +public: + void SetConfig(const DescriptorConfig c) { config = c; } + void Run(http::Reply& reply, std::vector< _PathData > * path, PhantomNodes * phantomNodes, SearchEngineT * sEngine, unsigned distance) { + string tmp; + string lineString; + string startName; + string targetName; + double entireDistance = 0; + string startLoc, endLoc, bodyString; + string direction = "East"; + reply.content += ("\n"); + reply.content += "\n"; + + reply.content += ("\t\n"); + + if(distance != UINT_MAX) { + unsigned streetID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); + startName = sEngine->GetEscapedNameForNameID(streetID); + streetID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); + targetName = sEngine->GetEscapedNameForNameID(streetID); + convertLatLon(phantomNodes->startCoord.lat, tmp); + bodyString += ("\t\tstartCoord.lon, tmp); + bodyString += (" lon=\""+tmp+"\">"); + bodyString += ("\n\t\t\tStart from "); + bodyString += startName; + bodyString += (" and head "); + _Coordinate tmpCoord; + if(path->size() > 0) + sEngine->getNodeInfo(path->begin()->node, tmpCoord); + else + tmpCoord = phantomNodes->targetCoord; + + int angle = round(GetAngleBetweenTwoEdges(_Coordinate(phantomNodes->startCoord.lat, phantomNodes->startCoord.lon), tmpCoord, _Coordinate(tmpCoord.lat, tmpCoord.lon-1000))); + if(angle >= 23 && angle < 67) + direction = "South-East"; + if(angle >= 67 && angle < 113) + direction = "South"; + if(angle >= 113 && angle < 158) + direction = "South-West"; + if(angle >= 158 && angle < 202) + direction = "West"; + if(angle >= 202 && angle < 248) + direction = "North-West"; + if(angle >= 248 && angle < 292) + direction = "North"; + if(angle >= 292 && angle < 336) + direction = "North-East"; + + bodyString += direction; + + bodyString += ("\n\t\t\t\n\t\t\t\t"+direction+"\n"); + + _Coordinate previous(phantomNodes->startCoord.lat, phantomNodes->startCoord.lon); + _Coordinate next, current, lastPlace, startOfSegment; + stringstream numberString; + + double tempDist = 0; + double lengthOfInstruction = 0; + NodeID nextID = UINT_MAX; + NodeID nameID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); + short type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); + lastPlace.lat = phantomNodes->startCoord.lat; + lastPlace.lon = phantomNodes->startCoord.lon; + short nextType = SHRT_MAX; + short prevType = SHRT_MAX; + + for(vector< _PathData >::iterator it = path->begin(); it != path->end(); it++) { + sEngine->getNodeInfo(it->node, current); + startOfSegment = previous; + if(it==path->begin()){ + + tempDist += ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon); + numberString << 10*(round(tempDist/10.));; + bodyString+="\t\t\t\t"+numberString.str() +"m\n"; + numberString.str(""); + bodyString+="\t\t\t\n\t\t"; + } + + if(it==path->end()-1){ + next = _Coordinate(phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon); + nextID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); + nextType = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); + } else { + sEngine->getNodeInfo((it+1)->node, next); + nextID = sEngine->GetNameIDForOriginDestinationNodeID(it->node, (it+1)->node); + nextType = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(it->node, (it+1)->node); + } + + convertLatLon(current.lat, tmp); + bodyString += "\n\t\t\n"; + + double angle = GetAngleBetweenTwoEdges(startOfSegment, current, next); + if(178 > angle || 182 < angle) { + convertLatLon(current.lon, tmp); + lineString += tmp; + lineString += ","; + convertLatLon(current.lat, tmp); + lineString += tmp; + lineString += " "; + startOfSegment = current; + } + + if(nextID == nameID) { + int temp = ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon); + tempDist += temp; + numberString << 10*(round(temp/10.)); + bodyString += "\t\t\t\n\t\t\t\t"+numberString.str()+"m\n\t\t\t"; + numberString.str(""); + } else { + bodyString += "\t\t\t"; + if(type == 0 && prevType != 0) + bodyString += "enter motorway and "; + if(type != 0 && prevType == 0 ) + bodyString += "leave motorway and "; + + bodyString += "follow road "; + if(nameID != 0) + bodyString += sEngine->GetEscapedNameForNameID(nameID); + string lat; string lon; + convertLatLon(lastPlace.lon, lon); + convertLatLon(lastPlace.lat, lat); + lastPlace = current; + if(angle > 160 && angle < 200) { + bodyString += /* " (" << angle << ")*/"drive ahead, "; + } else if (angle > 290 && angle <= 360) { + bodyString += /*" (" << angle << ")*/ "turn sharp left, "; + } else if (angle > 230 && angle <= 290) { + bodyString += /*" (" << angle << ")*/ "turn left, "; + } else if (angle > 200 && angle <= 230) { + bodyString += /*" (" << angle << ") */"bear left, "; + } else if (angle > 130 && angle <= 160) { + bodyString += /*" (" << angle << ") */"bear right, "; + } else if (angle > 70 && angle <= 130) { + bodyString += /*" (" << angle << ") */"turn right, "; + } else { + bodyString += /*" (" << angle << ") */"turn sharp right, "; + } + bodyString += "\n\t\t\t\n\t\t\t\t"; + lengthOfInstruction = ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon)+tempDist; + entireDistance += lengthOfInstruction; + numberString << 10*(round(lengthOfInstruction/10.));; + bodyString += numberString.str(); + numberString.str(""); + bodyString += "m\n"; + tempDist = 0; + prevType = type; + bodyString += "\t\t\t"; + } + bodyString +="\n\t\t"; + nameID = nextID; + previous = current; + type = nextType; + } + convertLatLon(phantomNodes->targetCoord.lat, tmp); + bodyString += "\n\t\ttargetCoord.lon, tmp); + bodyString += "lon=\"" + tmp + "\">\n"; + bodyString += "\t\t\t"; + + nameID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); + type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); + bodyString += "follow road "; + + bodyString += sEngine->GetEscapedNameForNameID(nameID); + bodyString += "\n\t\t\t\n\t\t\t\t"; + + lengthOfInstruction = ApproximateDistance(previous.lat, previous.lon, phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon) + tempDist; + entireDistance += lengthOfInstruction; + numberString << 10*(round(lengthOfInstruction/10.)); + bodyString += numberString.str(); + numberString.str(""); + bodyString += "m\n "; + string lat; string lon; + + bodyString += "\t\t\t\n\t\t"; + + + //put targetCoord to linestring + convertLatLon(phantomNodes->targetCoord.lon, tmp); + lineString += tmp; + lineString += ","; + convertLatLon(phantomNodes->targetCoord.lat, tmp); + lineString += tmp; + ostringstream s; + s << 10*(round(entireDistance/10.)); + reply.content += ("\t\t"+s.str()+"m\n"); + int travelTime = (distance/60) + 1; + s.str(""); + s << travelTime; + reply.content += ("\t\t\n"); + reply.content += ("\t\n\t\n"); + + if(config.geometry){ + reply.content +=(bodyString+"\n"); + } + } + else { + reply.content += "\t\n\t\n"; + } + reply.content += "\t\n"; + } +private: +}; +#endif /* GPX_DESCRIPTOR_H_ */ diff --git a/Plugins/RoutePlugin.h b/Plugins/RoutePlugin.h index 1b4d3a278..7f2916f92 100644 --- a/Plugins/RoutePlugin.h +++ b/Plugins/RoutePlugin.h @@ -34,6 +34,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "RouteParameters.h" #include "KMLDescriptor.h" #include "JSONDescriptor.h" +#include "GPXDescriptor.h" #include "../DataStructures/HashTable.h" #include "../DataStructures/StaticGraph.h" @@ -53,6 +54,7 @@ public: descriptorTable.Set("", 0); //default descriptor descriptorTable.Set("kml", 0); descriptorTable.Set("json", 1); + descriptorTable.Set("gpx", 2); } ~RoutePlugin() { @@ -131,6 +133,10 @@ public: case 1: desc = new JSONDescriptor > >(); + break; + case 2: + desc = new GPXDescriptor > >(); + break; default: desc = new KMLDescriptor > >(); @@ -169,6 +175,13 @@ public: 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";