diff --git a/DataStructures/PolylineCompressor.h b/DataStructures/PolylineCompressor.h new file mode 100644 index 000000000..a7898863e --- /dev/null +++ b/DataStructures/PolylineCompressor.h @@ -0,0 +1,78 @@ +/* + 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 "ExtractorStructs.h" + +class PolylineCompressor { +private: + inline string encodeSignedNumber(int number) const { + int signedNumber = number << 1; + if (number < 0) { + signedNumber = ~(signedNumber); + } + return (encodeNumber(signedNumber)); + } + + inline string encodeNumber(int numberToEncode) const { + ostringstream encodeString; + + while (numberToEncode >= 0x20) { + int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63; + encodeString << (static_cast (nextValue)); + numberToEncode >>= 5; + } + + numberToEncode += 63; + encodeString << (static_cast (numberToEncode)); + + return encodeString.str(); + } +public: + inline void printEncodedString(vector<_Coordinate>& polyline, string &output) { + output += encodeSignedNumber(polyline[0].lat); + output += encodeSignedNumber(polyline[0].lon); + for(unsigned i = 1; i < polyline.size(); i++) { + output += encodeSignedNumber(polyline[i].lat - polyline[i-1].lat); + output += encodeSignedNumber(polyline[i].lon - polyline[i-1].lon); + } + } + + inline void printUnencodedString(vector<_Coordinate> & polyline, string & output) { + string tmp; + for(unsigned i = 0; i < polyline.size(); i++) { + convertLatLon(polyline[i].lat, tmp); + output += "["; + output += tmp; + convertLatLon(polyline[i].lon, tmp); + output += ", "; + output += tmp; + output += "]"; + if( i < polyline.size()-1 ) { + output += ","; + } + } + + } +}; + +#endif /* POLYLINECOMPRESSOR_H_ */ diff --git a/Plugins/BaseDescriptor.h b/Plugins/BaseDescriptor.h index 316acb784..1172265b0 100644 --- a/Plugins/BaseDescriptor.h +++ b/Plugins/BaseDescriptor.h @@ -29,13 +29,17 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../typedefs.h" #include "../DataStructures/ExtractorStructs.h" #include "../DataStructures/HashTable.h" +#include "../DataStructures/PolylineCompressor.h" #include "../Util/StrIngUtil.h" struct DescriptorConfig { - DescriptorConfig() : instructions(true), geometry(true), z(18) {} + DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {} bool instructions; bool geometry; + bool encodeGeometry; unsigned short z; + + PolylineCompressor pc; }; template diff --git a/Plugins/JSONDescriptor.h b/Plugins/JSONDescriptor.h index ec5a3510f..8df495a41 100644 --- a/Plugins/JSONDescriptor.h +++ b/Plugins/JSONDescriptor.h @@ -19,6 +19,7 @@ or see http://www.gnu.org/licenses/agpl.txt. */ #include "BaseDescriptor.h" +#include "../DataStructures/PolylineCompressor.h" #ifndef JSONDESCRIPTOR_H_ #define JSONDESCRIPTOR_H_ @@ -29,6 +30,7 @@ template class JSONDescriptor : public BaseDescriptor { private: DescriptorConfig config; + vector<_Coordinate> polyline; public: JSONDescriptor() {} void SetConfig(const DescriptorConfig c) { @@ -104,13 +106,7 @@ public: routeInstructionString += direction; //put start coord to linestring; - convertLatLon(phantomNodes->startCoord.lat, tmp); - routeGeometryString += "["; - routeGeometryString += tmp; - routeGeometryString += ", "; - convertLatLon(phantomNodes->startCoord.lon, tmp); - routeGeometryString += tmp; - routeGeometryString += "],"; + polyline.push_back(phantomNodes->startCoord); _Coordinate previous(phantomNodes->startCoord.lat, phantomNodes->startCoord.lon); _Coordinate next, current, lastPlace, startOfSegment; @@ -147,13 +143,8 @@ public: // std::cout << "Area for: " << area << std::endl; if(area > areaThresholds[config.z] || 19 == config.z) { painted++; - convertLatLon(current.lat, tmp); - routeGeometryString += "["; - routeGeometryString += tmp; - routeGeometryString += ", "; - convertLatLon(current.lon, tmp); - routeGeometryString += tmp; - routeGeometryString += "],"; + polyline.push_back(current); + position++; startOfSegment = current; } else { @@ -200,8 +191,6 @@ public: routeInstructionString += "],"; string lat; string lon; - convertLatLon(lastPlace.lon, lon); - convertLatLon(lastPlace.lat, lat); lastPlace = current; routeInstructionString += "[\""; @@ -264,13 +253,7 @@ public: string lat; string lon; //put targetCoord to linestring - convertLatLon(phantomNodes->targetCoord.lat, tmp); - routeGeometryString += "["; - routeGeometryString += tmp; - routeGeometryString += ", "; - convertLatLon(phantomNodes->targetCoord.lon, tmp); - routeGeometryString += tmp; - routeGeometryString += "]"; + polyline.push_back(phantomNodes->targetCoord); position++; //give complete distance in meters; @@ -305,6 +288,11 @@ public: reply.content += "},"; reply.content += "\"route_geometry\": ["; if(config.geometry) { + if(config.encodeGeometry) + config.pc.printEncodedString(polyline, routeGeometryString); + else + config.pc.printUnencodedString(polyline, routeGeometryString); + reply.content += routeGeometryString; } reply.content += "],"; diff --git a/Plugins/RoutePlugin.h b/Plugins/RoutePlugin.h index 0bd0ec68b..1b4d3a278 100644 --- a/Plugins/RoutePlugin.h +++ b/Plugins/RoutePlugin.h @@ -119,6 +119,9 @@ public: descriptorConfig.geometry = false; } + if("cmp" == routeParameters.options.Find("geomformat") || "cmp6" == routeParameters.options.Find("geomformat") ) { + descriptorConfig.encodeGeometry = true; + } switch(descriptorType){ case 0: