diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 3bf2888ac..49cb16b04 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -138,7 +138,6 @@ public: const NodeID target = edges[i].target; const NodeID via = edges[i].data.via; const short turnType = edges[i].data.turnInstruction; - assert(turnType == 0 || turnType == 1); //remove eigenloops if ( source == target ) { i++; diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 5dcf146fa..e4aafab78 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -50,6 +50,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectorweight(), 1 ); assert( edge.data.distance > 0 ); edge.data.shortcut = false; + edge.data.roundabout = i->isRoundabout(); edge.data.middleName.nameID = i->name(); edge.data.type = i->type(); edge.data.forward = i->isForward(); @@ -186,10 +187,28 @@ short EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const N _NodeBasedDynamicGraph::EdgeData data1 = _nodeBasedGraph->GetEdgeData(edge1); _NodeBasedDynamicGraph::EdgeData data2 = _nodeBasedGraph->GetEdgeData(edge2); - if(data1.middleName.nameID == data2.middleName.nameID) { + double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); + + if(data1.middleName.nameID == data2.middleName.nameID) + return TurnInstructions.NoTurn; + + //Is turn on roundabout? + if(data1.roundabout || data2.roundabout) { + //We are entering the roundabout + if(!data1.roundabout && data2.roundabout) + return TurnInstructions.EnterRoundAbout; + //We are leaving the roundabout + if(data1.roundabout && !data2.roundabout) + return TurnInstructions.LeaveRoundAbout; + //Is a turn possible? If yes, we stay on the roundabout! + if(_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v) > 1) + return TurnInstructions.StayOnRoundAbout; + //No turn possible. return TurnInstructions.NoTurn; } - return TurnInstructions.GoStraight; + + + return TurnInstructions.GetTurnDirectionOfInstruction(angle); } unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const { @@ -199,3 +218,17 @@ unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const { EdgeBasedGraphFactory::~EdgeBasedGraphFactory() { } +/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/ +template +double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const { + const int v1x = A.lon - C.lon; + const int v1y = A.lat - C.lat; + const int v2x = B.lon - C.lon; + const int v2y = B.lat - C.lat; + + double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI; + while(angle < 0) + angle += 360; + + return angle; +} diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 0ec7d9d5b..5fa1007fa 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -49,6 +49,7 @@ private: bool shortcut; bool forward; bool backward; + bool roundabout; short type; _MiddleName middleName; } data; @@ -94,6 +95,8 @@ private: std::vector<_EdgeBasedEdge> edgeBasedEdges; std::vector edgeBasedNodes; + template + double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const; public: template< class InputEdgeT > explicit EdgeBasedGraphFactory(int nodes, std::vector & inputEdges, std::vector<_Restriction> & inputRestrictions, std::vector & nI); diff --git a/DataStructures/ExtractorCallBacks.h b/DataStructures/ExtractorCallBacks.h index cfa2f0b19..e2e31d301 100644 --- a/DataStructures/ExtractorCallBacks.h +++ b/DataStructures/ExtractorCallBacks.h @@ -134,6 +134,9 @@ public: else if("no" == accessClass) w.access = false; + if(junction == "roundabout") { + w.roundabout = true; + } //Let's process oneway property, if speed profile obeys to it if(oneway != "no" && oneway != "false" && oneway != "0" && settings.obeyOneways) { //if oneway tag is in forward direction or if actually roundabout @@ -175,7 +178,7 @@ public: } for(vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { - externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID)); + externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout)); externalMemory->usedNodeIDs.push_back(w.path[n]); } externalMemory->usedNodeIDs.push_back(w.path[w.path.size()-1]); diff --git a/DataStructures/ExtractorStructs.h b/DataStructures/ExtractorStructs.h index a7d0c7ad6..0f5ead963 100644 --- a/DataStructures/ExtractorStructs.h +++ b/DataStructures/ExtractorStructs.h @@ -79,6 +79,7 @@ struct _Way { type = -1; useful = false; access = true; + roundabout = false; } enum { @@ -89,8 +90,9 @@ struct _Way { std::string name; double speed; short type; - bool useful:1; - bool access:1; + bool useful; + bool access; + bool roundabout; std::vector< NodeID > path; HashTable keyVals; }; @@ -124,16 +126,17 @@ struct _Relation { }; struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid) { } + _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false) {}; + _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra) { } NodeID start; NodeID target; short type; short direction; double speed; unsigned nameID; + bool isRoundabout; _Coordinate startCoord; _Coordinate targetCoord; diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index 195caa6ea..14ae31463 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -42,10 +42,10 @@ public: /** Default constructor. target and weight are set to 0.*/ NodeBasedEdge() : - _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0) { assert(false); } //shall not be used. + _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false) { assert(false); } //shall not be used. - explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty) : - _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty) { assert(ty >= 0); } + explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra) : + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra) { assert(ty >= 0); } NodeID target() const {return _target; } NodeID source() const {return _source; } @@ -56,6 +56,7 @@ public: bool isBackward() const { return backward; } bool isForward() const { return forward; } bool isLocatable() const { return _type != 14; } + bool isRoundabout() const { return _roundabout; } NodeID _source; NodeID _target; @@ -64,6 +65,7 @@ public: bool forward; bool backward; short _type; + bool _roundabout; }; class EdgeBasedEdge { diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index eea6ef459..5a6b86412 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -37,8 +37,11 @@ struct TurnInstructionsClass { const static short TurnSlightLeft = 8; const static short ReachViaPoint = 9; const static short HeadOn = 10; + const static short EnterRoundAbout = 11; + const static short LeaveRoundAbout = 12; + const static short StayOnRoundAbout = 13; - std::string TurnStrings[11]; + std::string TurnStrings[14]; //This is a hack until c++0x is available enough to use initializer lists. TurnInstructionsClass(){ @@ -53,7 +56,84 @@ struct TurnInstructionsClass { TurnStrings [8] = "Turn slight left"; TurnStrings [9] = "Reach via point"; TurnStrings[10] = "Head"; + TurnStrings[11] = "Enter round-about"; + TurnStrings[12] = "Leave round-about"; + TurnStrings[13] = "Stay on round-about"; }; + + static inline double GetTurnDirectionOfInstruction( const double angle ) { + if(angle >= 23 && angle < 67) { + return TurnSharpRight; + } + if (angle >= 67 && angle < 113) { + return TurnRight; + } + if (angle >= 113 && angle < 158) { + return TurnSlightRight; + } + if (angle >= 158 && angle < 202) { + return GoStraight; + } + if (angle >= 202 && angle < 248) { + return TurnSlightLeft; + } + if (angle >= 248 && angle < 292) { + return TurnLeft; + } + if (angle >= 292 && angle < 336) { + return TurnSharpLeft; + } + return 5; + } + + static inline bool TurnIsNecessary ( const short turnInstruction ) { + if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction) + return false; + return true; + } + + // static inline void getDirectionOfInstruction(double angle, DirectionOfInstruction & dirInst) { + // if(angle >= 23 && angle < 67) { + // dirInst.direction = "southeast"; + // dirInst.shortDirection = "SE"; + // return; + // } + // if(angle >= 67 && angle < 113) { + // dirInst.direction = "south"; + // dirInst.shortDirection = "S"; + // return; + // } + // if(angle >= 113 && angle < 158) { + // dirInst.direction = "southwest"; + // dirInst.shortDirection = "SW"; + // return; + // } + // if(angle >= 158 && angle < 202) { + // dirInst.direction = "west"; + // dirInst.shortDirection = "W"; + // return; + // } + // if(angle >= 202 && angle < 248) { + // dirInst.direction = "northwest"; + // dirInst.shortDirection = "NW"; + // return; + // } + // if(angle >= 248 && angle < 292) { + // dirInst.direction = "north"; + // dirInst.shortDirection = "N"; + // return; + // } + // if(angle >= 292 && angle < 336) { + // dirInst.direction = "northeast"; + // dirInst.shortDirection = "NE"; + // return; + // } + // dirInst.direction = "East"; + // dirInst.shortDirection = "E"; + // return; + // } + // + }; static TurnInstructionsClass TurnInstructions; diff --git a/Descriptors/BaseDescriptor.h b/Descriptors/BaseDescriptor.h index 20050cffe..759965add 100644 --- a/Descriptors/BaseDescriptor.h +++ b/Descriptors/BaseDescriptor.h @@ -34,22 +34,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../Plugins/RawRouteData.h" -static double areaThresholds[19] = { 5000, 5000, 5000, 5000, 5000, 2500, 2000, 1500, 800, 400, 250, 150, 100, 75, 25, 20, 10, 5, 0 }; - -/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/ -static double GetAngleBetweenTwoEdges(const _Coordinate& A, const _Coordinate& C, const _Coordinate& B) { - int v1x = A.lon - C.lon; - int v1y = A.lat - C.lat; - int v2x = B.lon - C.lon; - int v2y = B.lat - C.lat; - - double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI; - while(angle < 0) - angle += 360; - - return angle; -} - struct _RouteSummary { std::string lengthString; std::string durationString; diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp index 1784a0416..4e040e168 100644 --- a/Descriptors/DescriptionFactory.cpp +++ b/Descriptors/DescriptionFactory.cpp @@ -38,7 +38,7 @@ void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) { pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) ); } -inline void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) { +void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) { pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) ); } diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h index f41e78fff..ac054bae1 100644 --- a/Descriptors/DescriptionFactory.h +++ b/Descriptors/DescriptionFactory.h @@ -50,87 +50,10 @@ public: void AppendEncodedPolylineString(std::string & output, bool isEncoded); unsigned Run(const unsigned zoomLevel); -// static inline void getDirectionOfInstruction(double angle, DirectionOfInstruction & dirInst) { -// if(angle >= 23 && angle < 67) { -// dirInst.direction = "southeast"; -// dirInst.shortDirection = "SE"; -// return; -// } -// if(angle >= 67 && angle < 113) { -// dirInst.direction = "south"; -// dirInst.shortDirection = "S"; -// return; -// } -// if(angle >= 113 && angle < 158) { -// dirInst.direction = "southwest"; -// dirInst.shortDirection = "SW"; -// return; -// } -// if(angle >= 158 && angle < 202) { -// dirInst.direction = "west"; -// dirInst.shortDirection = "W"; -// return; -// } -// if(angle >= 202 && angle < 248) { -// dirInst.direction = "northwest"; -// dirInst.shortDirection = "NW"; -// return; -// } -// if(angle >= 248 && angle < 292) { -// dirInst.direction = "north"; -// dirInst.shortDirection = "N"; -// return; -// } -// if(angle >= 292 && angle < 336) { -// dirInst.direction = "northeast"; -// dirInst.shortDirection = "NE"; -// return; -// } -// dirInst.direction = "East"; -// dirInst.shortDirection = "E"; -// return; -// } -// -// static inline void getTurnDirectionOfInstruction(double angle, std::string & output) { -// if(angle >= 23 && angle < 67) { -// output = "Turn sharp right"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// if (angle >= 67 && angle < 113) { -// output = "Turn right"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// if (angle >= 113 && angle < 158) { -// output = "Bear right"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// -// if (angle >= 158 && angle < 202) { -// output = "Continue"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// if (angle >= 202 && angle < 248) { -// output = "Bear left"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// if (angle >= 248 && angle < 292) { -// output = "Turn left"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// if (angle >= 292 && angle < 336) { -// output = "Turn sharp left"; -// // cout << "angle " << angle << "-> " << output << endl; -// return; -// } -// output = "U-Turn"; -// // cout << "angle " << angle << "-> " << output << endl; -// } +}; + +#endif /* DESCRIPTIONFACTORY_H_ */ + //private: // void appendInstructionNameToString(const std::string & nameOfStreet, const std::string & instructionOrDirection, std::string &output, bool firstAdvice = false) { // output += "["; @@ -173,6 +96,3 @@ public: // } // output += "]"; // } -}; - -#endif /* DESCRIPTIONFACTORY_H_ */ diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index 1518e217c..3fae495e4 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -100,10 +100,11 @@ public: std::string tmpDist, tmpLength, tmp; //Fetch data from Factory and generate a string from it. BOOST_FOREACH(SegmentInformation segment, descriptionFactory.pathDescription) { - if(0 != segment.turnInstruction) { + if(TurnInstructions.TurnIsNecessary( segment.turnInstruction) ) { if(0 != prefixSumOfNecessarySegments) reply.content += ","; reply.content += "[\""; + INFO("INstruction: " << segment.turnInstruction); reply.content += TurnInstructions.TurnStrings[segment.turnInstruction]; reply.content += "\",\""; reply.content += sEngine.GetEscapedNameForNameID(segment.nameID); diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index 17392f6b8..e1d4d9464 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -142,18 +142,21 @@ NodeID readBinaryOSRMGraphFromStream(istream &in, vector& edgeList, vecto } edgeList.reserve(m); + EdgeWeight weight; + short type; + NodeID nameID; + int length; + bool isRoundabout; + for (EdgeID i=0; i 0); assert(weight > 0); @@ -186,7 +189,7 @@ NodeID readBinaryOSRMGraphFromStream(istream &in, vector& edgeList, vecto if(source == UINT_MAX || target == UINT_MAX) { cerr << "nonexisting source or target" << endl; exit(0); } - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type ); + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout ); edgeList.push_back(inputEdge); } ext2IntNodeMap.clear(); diff --git a/extractor.cpp b/extractor.cpp index a3c364428..062417a08 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -429,6 +429,7 @@ int main (int argc, char *argv[]) { short edgeType = edgeIT->type; fout.write((char*)&edgeType, sizeof(short)); fout.write((char*)&edgeIT->nameID, sizeof(unsigned)); + fout.write((char *)&edgeIT->isRoundabout, sizeof(bool)); } ++usedEdgeCounter; ++edgeIT; @@ -443,7 +444,6 @@ int main (int argc, char *argv[]) { fout.close(); cout << "ok" << endl; time = get_timestamp(); - INFO("Written edges: " << usedEdgeCounter << " at " << positionInFile); cout << "[extractor] writing street name index ... " << flush; vector * nameIndex = new vector(externalMemory.nameVector.size()+1, 0); outputFileName.append(".names");