diff --git a/CMakeLists.txt b/CMakeLists.txt index eea2cf002..3a7a652be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ if(WIN32 AND MSVC_VERSION LESS 1800) endif() option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF) +option(DEBUG_GEOMETRY "Enables an option to dump GeoJSON of the final routing graph" OFF) option(BUILD_TOOLS "Build OSRM tools" OFF) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) @@ -332,6 +333,11 @@ if (ENABLE_JSON_LOGGING) add_definitions(-DENABLE_JSON_LOGGING) endif() +if (DEBUG_GEOMETRY) + message(STATUS "Enabling final edge weight GeoJSON output option") + add_definitions(-DDEBUG_GEOMETRY) +endif() + if(BUILD_TOOLS) message(STATUS "Activating OSRM internal tools") find_package(GDAL) diff --git a/appveyor-build.bat b/appveyor-build.bat index babefe168..a1e96031c 100644 --- a/appveyor-build.bat +++ b/appveyor-build.bat @@ -6,6 +6,8 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SET PROJECT_DIR=%CD% ECHO PROJECT_DIR^: %PROJECT_DIR% +ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS% +ECHO cmake^: && cmake --version ECHO activating VS command prompt ... SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% @@ -50,7 +52,7 @@ set TBB_ARCH_PLATFORM=intel64/vc14 ECHO calling cmake .... cmake .. ^ --G "Visual Studio 14 Win64" ^ +-G "Visual Studio 14 2015 Win64" ^ -DBOOST_ROOT=%BOOST_ROOT% ^ -DBoost_ADDITIONAL_VERSIONS=1.58 ^ -DBoost_USE_MULTITHREADED=ON ^ diff --git a/build-local.bat b/build-local.bat index e1ae94a3b..90380df99 100644 --- a/build-local.bat +++ b/build-local.bat @@ -11,7 +11,8 @@ SET CONFIGURATION=Release FOR /F "tokens=*" %%i in ('git rev-parse --abbrev-ref HEAD') do SET APPVEYOR_REPO_BRANCH=%%i ECHO APPVEYOR_REPO_BRANCH^: %APPVEYOR_REPO_BRANCH% -SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.1.0-win32-x86\bin;%PATH% +::SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.1.0-win32-x86\bin;%PATH% +SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.4.0-win32-x86\bin;%PATH% SET PATH=C:\Program Files\7-Zip;%PATH% powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force diff --git a/contractor/contractor.hpp b/contractor/contractor.hpp index 07a21dc50..c7d17bc72 100644 --- a/contractor/contractor.hpp +++ b/contractor/contractor.hpp @@ -55,6 +55,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class Contractor { + public: + struct RemainingNodeData + { + RemainingNodeData() : id(0), is_independent(false) {} + NodeID id : 31; + bool is_independent : 1; + }; + private: struct ContractorEdgeData @@ -127,13 +135,6 @@ class Contractor } }; - struct RemainingNodeData - { - RemainingNodeData() : id(0), is_independent(false) {} - NodeID id : 31; - bool is_independent : 1; - }; - struct ThreadDataContainer { explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {} diff --git a/contractor/contractor_options.cpp b/contractor/contractor_options.cpp index 0f2f66538..d48346563 100644 --- a/contractor/contractor_options.cpp +++ b/contractor/contractor_options.cpp @@ -56,13 +56,20 @@ ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &cont boost::program_options::value(&contractor_config.requested_num_threads) ->default_value(tbb::task_scheduler_init::default_num_threads()), "Number of threads to use")( - "core,k", - boost::program_options::value(&contractor_config.core_factor)->default_value(1.0), - "Percentage of the graph (in vertices) to contract [0.1]")( + "core,k", boost::program_options::value(&contractor_config.core_factor) + ->default_value(1.0),"Percentage of the graph (in vertices) to contract [0..1]")( + "segment-speed-file", boost::program_options::value(&contractor_config.segment_speed_lookup_path), + "Lookup file containing nodeA,nodeB,speed data to adjust edge weights")( "level-cache,o", boost::program_options::value(&contractor_config.use_cached_priority)->default_value(false), "Use .level file to retain the contaction level for each node from the last run."); +#ifdef DEBUG_GEOMETRY + config_options.add_options()( + "debug-geometry", boost::program_options::value(&contractor_config.debug_geometry_path) + ,"Write out edge-weight debugging geometry data in GeoJSON format to this file"); +#endif + // hidden options, will be allowed both on command line and in config file, but will not be // shown to the user boost::program_options::options_description hidden_options("Hidden options"); diff --git a/contractor/contractor_options.hpp b/contractor/contractor_options.hpp index d948ead87..5932b78c6 100644 --- a/contractor/contractor_options.hpp +++ b/contractor/contractor_options.hpp @@ -66,6 +66,9 @@ struct ContractorConfig std::string segment_speed_lookup_path; +#ifdef DEBUG_GEOMETRY + std::string debug_geometry_path; +#endif }; struct ContractorOptions diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index 23032b2ab..08b56be31 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -55,6 +55,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "../util/debug_geometry.hpp" + Prepare::~Prepare() {} int Prepare::Run() @@ -95,7 +97,8 @@ int Prepare::Run() ReadNodeLevels(node_levels); } DeallocatingVector contracted_edge_list; - ContractGraph(max_edge_id, edge_based_edge_list, contracted_edge_list, is_core_node, node_levels); + ContractGraph(max_edge_id, edge_based_edge_list, contracted_edge_list, is_core_node, + node_levels); TIMER_STOP(contraction); SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec"; @@ -186,12 +189,14 @@ std::size_t Prepare::LoadEdgeExpandedGraph(std::string const &edge_based_graph_f } } + DEBUG_GEOMETRY_START(config); + // TODO: can we read this in bulk? DeallocatingVector isn't necessarily // all stored contiguously for (; number_of_edges > 0; --number_of_edges) { EdgeBasedEdge inbuffer; - input_stream.read((char *)&inbuffer, sizeof(EdgeBasedEdge)); + input_stream.read((char *) &inbuffer, sizeof(EdgeBasedEdge)); if (update_edge_weights) { @@ -232,11 +237,23 @@ std::size_t Prepare::LoadEdgeExpandedGraph(std::string const &edge_based_graph_f std::max(1, static_cast(std::floor( (segment_length * 10.) / (speed_iter->second / 3.6) + .5))); new_weight += new_segment_weight; + + DEBUG_GEOMETRY_EDGE( + new_segment_weight, + segment_length, + previous_osm_node_id, + this_osm_node_id); } else { // If no lookup found, use the original weight value for this segment new_weight += segment_weight; + + DEBUG_GEOMETRY_EDGE( + segment_weight, + segment_length, + previous_osm_node_id, + this_osm_node_id); } previous_osm_node_id = this_osm_node_id; @@ -247,33 +264,31 @@ std::size_t Prepare::LoadEdgeExpandedGraph(std::string const &edge_based_graph_f edge_based_edge_list.emplace_back(std::move(inbuffer)); } + + DEBUG_GEOMETRY_STOP(); SimpleLogger().Write() << "Done reading edges"; return max_edge_id; } void Prepare::ReadNodeLevels(std::vector &node_levels) const { - boost::filesystem::ifstream order_input_stream(config.level_output_path, - std::ios::binary); + boost::filesystem::ifstream order_input_stream(config.level_output_path, std::ios::binary); unsigned level_size; order_input_stream.read((char *)&level_size, sizeof(unsigned)); node_levels.resize(level_size); - order_input_stream.read((char *)node_levels.data(), - sizeof(float) * node_levels.size()); + order_input_stream.read((char *)node_levels.data(), sizeof(float) * node_levels.size()); } void Prepare::WriteNodeLevels(std::vector &&in_node_levels) const { std::vector node_levels(std::move(in_node_levels)); - boost::filesystem::ofstream order_output_stream(config.level_output_path, - std::ios::binary); + boost::filesystem::ofstream order_output_stream(config.level_output_path, std::ios::binary); unsigned level_size = node_levels.size(); order_output_stream.write((char *)&level_size, sizeof(unsigned)); - order_output_stream.write((char *)node_levels.data(), - sizeof(float) * node_levels.size()); + order_output_stream.write((char *)node_levels.data(), sizeof(float) * node_levels.size()); } void Prepare::WriteCoreNodeMarker(std::vector &&in_is_core_node) const diff --git a/contractor/processing_chain.hpp b/contractor/processing_chain.hpp index 0de1bef9d..0eb65553d 100644 --- a/contractor/processing_chain.hpp +++ b/contractor/processing_chain.hpp @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PROCESSING_CHAIN_HPP #define PROCESSING_CHAIN_HPP +#include "contractor.hpp" #include "contractor_options.hpp" #include "../data_structures/query_edge.hpp" #include "../data_structures/static_graph.hpp" diff --git a/extractor/edge_based_graph_factory.cpp b/extractor/edge_based_graph_factory.cpp index f775e7a19..1f23f2535 100644 --- a/extractor/edge_based_graph_factory.cpp +++ b/extractor/edge_based_graph_factory.cpp @@ -35,6 +35,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../util/timing_util.hpp" #include "../util/osrm_exception.hpp" +#include "../util/debug_geometry.hpp" + #include #include @@ -222,12 +224,20 @@ void EdgeBasedGraphFactory::FlushVectorToStream( original_edge_data_vector.clear(); } +#ifdef DEBUG_GEOMETRY void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, lua_State *lua_state, const std::string &edge_segment_lookup_filename, const std::string &edge_penalty_filename, - const bool generate_edge_lookup - ) + const bool generate_edge_lookup, + const std::string &debug_turns_path) +#else +void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, + lua_State *lua_state, + const std::string &edge_segment_lookup_filename, + const std::string &edge_penalty_filename, + const bool generate_edge_lookup) +#endif { TIMER_START(renumber); m_max_edge_id = RenumberEdges() - 1; @@ -238,9 +248,16 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, TIMER_STOP(generate_nodes); TIMER_START(generate_edges); +#ifdef DEBUG_GEOMETRY GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state, - edge_segment_lookup_filename,edge_penalty_filename, generate_edge_lookup - ); + edge_segment_lookup_filename,edge_penalty_filename, + generate_edge_lookup, debug_turns_path); +#else + GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state, + edge_segment_lookup_filename,edge_penalty_filename, + generate_edge_lookup); +#endif + TIMER_STOP(generate_edges); SimpleLogger().Write() << "Timing statistics for edge-expanded graph:"; @@ -324,12 +341,20 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() } /// Actually it also generates OriginalEdgeData and serializes them... +#ifdef DEBUG_GEOMETRY void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( const std::string &original_edge_data_filename, lua_State *lua_state, const std::string &edge_segment_lookup_filename, const std::string &edge_fixed_penalties_filename, - const bool generate_edge_lookup - ) + const bool generate_edge_lookup, + const std::string &debug_turns_path) +#else +void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( + const std::string &original_edge_data_filename, lua_State *lua_state, + const std::string &edge_segment_lookup_filename, + const std::string &edge_fixed_penalties_filename, + const bool generate_edge_lookup) +#endif { SimpleLogger().Write() << "generating edge-expanded edges"; @@ -362,9 +387,13 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( Percent progress(m_node_based_graph->GetNumberOfNodes()); +#ifdef DEBUG_GEOMETRY + DEBUG_TURNS_START(debug_turns_path); +#endif + for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) { - progress.printStatus(node_u); + //progress.printStatus(node_u); for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u)) { if (m_node_based_graph->GetEdgeData(e1).reversed) @@ -435,6 +464,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( if (m_traffic_lights.find(node_v) != m_traffic_lights.end()) { distance += speed_profile.traffic_signal_penalty; + + DEBUG_SIGNAL(node_v, m_node_info_list, speed_profile.traffic_signal_penalty); } // unpack last node of first segment if packed @@ -457,8 +488,12 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( if (turn_instruction == TurnInstruction::UTurn) { distance += speed_profile.u_turn_penalty; + + DEBUG_UTURN(node_v, m_node_info_list, speed_profile.u_turn_penalty); } + DEBUG_TURN(node_v, m_node_info_list, first_coordinate, turn_angle, turn_penalty); + distance += turn_penalty; const bool edge_is_compressed = m_compressed_edge_container.HasEntryForID(e1); @@ -541,6 +576,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( } } } + + DEBUG_TURNS_STOP(); + FlushVectorToStream(edge_data_file, original_edge_data_vector); edge_data_file.seekp(std::ios::beg); diff --git a/extractor/edge_based_graph_factory.hpp b/extractor/edge_based_graph_factory.hpp index 74e50cea3..80e294be9 100644 --- a/extractor/edge_based_graph_factory.hpp +++ b/extractor/edge_based_graph_factory.hpp @@ -50,6 +50,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + struct lua_State; class EdgeBasedGraphFactory @@ -66,12 +68,20 @@ class EdgeBasedGraphFactory const std::vector &node_info_list, SpeedProfileProperties speed_profile); +#ifdef DEBUG_GEOMETRY void Run(const std::string &original_edge_data_filename, lua_State *lua_state, const std::string &edge_segment_lookup_filename, const std::string &edge_penalty_filename, - const bool generate_edge_lookup - ); + const bool generate_edge_lookup, + const std::string &debug_turns_path); +#else + void Run(const std::string &original_edge_data_filename, + lua_State *lua_state, + const std::string &edge_segment_lookup_filename, + const std::string &edge_penalty_filename, + const bool generate_edge_lookup); +#endif void GetEdgeBasedEdges(DeallocatingVector &edges); @@ -103,12 +113,20 @@ class EdgeBasedGraphFactory void CompressGeometry(); unsigned RenumberEdges(); void GenerateEdgeExpandedNodes(); +#ifdef DEBUG_GEOMETRY void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename, lua_State *lua_state, const std::string &edge_segment_lookup_filename, const std::string &edge_fixed_penalties_filename, - const bool generate_edge_lookup - ); + const bool generate_edge_lookup, + const std::string &debug_turns_path); +#else + void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename, + lua_State *lua_state, + const std::string &edge_segment_lookup_filename, + const std::string &edge_fixed_penalties_filename, + const bool generate_edge_lookup); +#endif void InsertEdgeBasedNode(const NodeID u, const NodeID v); diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 27230b28d..029c47c0a 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -536,6 +536,9 @@ extractor::BuildEdgeExpandedGraph(std::vector &internal_to_external_n config.edge_segment_lookup_path, config.edge_penalty_path, config.generate_edge_lookup +#ifdef DEBUG_GEOMETRY + , config.debug_turns_path +#endif ); lua_close(lua_state); @@ -543,11 +546,6 @@ extractor::BuildEdgeExpandedGraph(std::vector &internal_to_external_n edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list); auto max_edge_id = edge_based_graph_factory.GetHighestEdgeID(); - // danpat TODO: somewhere right around here, we will need to - // use the internal_to_external_node_map (which contains original OSM node ids) - // the edges from the compressed edge container - // and the edge-based-edges - const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes(); return std::make_pair(number_of_node_based_nodes, max_edge_id); } diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index 629b9c67b..f15f64409 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -66,6 +66,12 @@ ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extrac &extractor_config.generate_edge_lookup)->implicit_value(true)->default_value(false), "Generate a lookup table for internal edge-expanded-edge IDs to OSM node pairs"); +#ifdef DEBUG_GEOMETRY + config_options.add_options()("debug-turns", + boost::program_options::value(&extractor_config.debug_turns_path), + "Write out GeoJSON with turn penalty data"); +#endif // DEBUG_GEOMETRY + // hidden options, will be allowed both on command line and in config file, but will not be // shown to the user boost::program_options::options_description hidden_options("Hidden options"); diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp index dd22b52ec..905430513 100644 --- a/extractor/extractor_options.hpp +++ b/extractor/extractor_options.hpp @@ -62,6 +62,9 @@ struct ExtractorConfig bool generate_edge_lookup; std::string edge_penalty_path; std::string edge_segment_lookup_path; +#ifdef DEBUG_GEOMETRY + std::string debug_turns_path; +#endif }; struct ExtractorOptions diff --git a/features/options/prepare/help.feature b/features/options/prepare/help.feature index 8d74c89d0..34ec3d5f3 100644 --- a/features/options/prepare/help.feature +++ b/features/options/prepare/help.feature @@ -17,7 +17,8 @@ Feature: osrm-prepare command line options: help And stdout should contain "--threads" And stdout should contain "--core" And stdout should contain "--level-cache" - And stdout should contain 18 lines + And stdout should contain "--segment-speed-file" + And stdout should contain 21 lines And it should exit with code 1 Scenario: osrm-prepare - Help, short @@ -33,7 +34,8 @@ Feature: osrm-prepare command line options: help And stdout should contain "--threads" And stdout should contain "--core" And stdout should contain "--level-cache" - And stdout should contain 18 lines + And stdout should contain "--segment-speed-file" + And stdout should contain 21 lines And it should exit with code 0 Scenario: osrm-prepare - Help, long @@ -49,5 +51,6 @@ Feature: osrm-prepare command line options: help And stdout should contain "--threads" And stdout should contain "--core" And stdout should contain "--level-cache" - And stdout should contain 18 lines + And stdout should contain "--segment-speed-file" + And stdout should contain 21 lines And it should exit with code 0 diff --git a/util/debug_geometry.hpp b/util/debug_geometry.hpp new file mode 100644 index 000000000..bfe4afa37 --- /dev/null +++ b/util/debug_geometry.hpp @@ -0,0 +1,198 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef DEBUG_GEOMETRY_H +#define DEBUG_GEOMETRY_H + +#include "../contractor/contractor_options.hpp" +#include "../data_structures/query_node.hpp" + +#ifndef DEBUG_GEOMETRY + +inline void DEBUG_GEOMETRY_START(ContractorConfig & /* config */) {} +inline void DEBUG_GEOMETRY_EDGE(int /* new_segment_weight */ , double /* segment_length */, + NodeID /* previous_osm_node_id */, NodeID /* this_osm_node_id */) {} +inline void DEBUG_GEOMETRY_STOP() {} + +inline void DEBUG_TURNS_START(const std::string & /* debug_turns_filename */) {} +inline void DEBUG_TURN( const NodeID /* node */, const std::vector& /* m_node_info_list */, + const FixedPointCoordinate & /* first_coordinate */, const int /* turn_angle */, + const int /* turn_penalty */) {} +inline void DEBUG_UTURN( const NodeID /* node */, const std::vector& /* m_node_info_list */, + const int /* uturn_penalty */ ) {} +inline void DEBUG_SIGNAL( const NodeID /* node */, const std::vector& /* m_node_info_list */, + const int /* signal_penalty */ ) {} + +inline void DEBUG_TURNS_STOP() {} + +#else // DEBUG_GEOMETRY + +#include +#include +#include +#include +#include + +#include "../include/osrm/coordinate.hpp" +#include "../algorithms/coordinate_calculation.hpp" + +boost::filesystem::ofstream debug_geometry_file; +bool dg_output_debug_geometry = false; +bool dg_first_debug_geometry = true; +char dg_time_buffer[80]; + +boost::filesystem::ofstream dg_debug_turns_file; +bool dg_output_turn_debug = false; +bool dg_first_turn_debug = true; + +inline void DEBUG_GEOMETRY_START(const ContractorConfig &config) +{ + time_t raw_time; + struct tm *timeinfo; + time(&raw_time); + timeinfo = localtime(&raw_time); + strftime(dg_time_buffer, 80, "%Y-%m-%d %H:%M %Z", timeinfo); + + dg_output_debug_geometry = config.debug_geometry_path != ""; + + if (dg_output_debug_geometry) + { + debug_geometry_file.open(config.debug_geometry_path, std::ios::binary); + debug_geometry_file << "{\"type\":\"FeatureCollection\", \"features\":[" << std::endl; + } +} + +inline void DEBUG_GEOMETRY_EDGE(int new_segment_weight, double segment_length, NodeID previous_osm_node_id, NodeID this_osm_node_id) +{ + if (dg_output_debug_geometry) + { + if (!dg_first_debug_geometry) + debug_geometry_file << "," << std::endl; + debug_geometry_file + << "{ \"type\":\"Feature\",\"properties\":{\"original\":false, " + "\"weight\":" + << new_segment_weight / 10.0 << ",\"speed\":" + << static_cast( + std::floor((segment_length / new_segment_weight) * 10. * 3.6)) + << ","; + debug_geometry_file << "\"from_node\": " << previous_osm_node_id + << ", \"to_node\": " << this_osm_node_id << ","; + debug_geometry_file << "\"timestamp\": \"" << dg_time_buffer << "\"},"; + debug_geometry_file + << "\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[!!" + << previous_osm_node_id << "!!],[!!" << this_osm_node_id << "!!]]}}" + << std::endl; + dg_first_debug_geometry = false; + } +} + +inline void DEBUG_GEOMETRY_STOP() +{ + if (dg_output_debug_geometry) + { + debug_geometry_file << std::endl << "]}" << std::endl; + debug_geometry_file.close(); + } +} + + +inline void DEBUG_TURNS_START(const std::string & debug_turns_path) +{ + dg_output_turn_debug = debug_turns_path != ""; + if (dg_output_turn_debug) + { + dg_debug_turns_file.open(debug_turns_path); + dg_debug_turns_file << "{\"type\":\"FeatureCollection\", \"features\":[" << std::endl; + } +} + +inline void DEBUG_SIGNAL( + const NodeID node, + const std::vector& m_node_info_list, + const int traffic_signal_penalty) +{ + if (dg_output_turn_debug) + { + const QueryNode &nodeinfo = m_node_info_list[node]; + if (!dg_first_turn_debug) dg_debug_turns_file << "," << std::endl; + dg_debug_turns_file << "{ \"type\":\"Feature\",\"properties\":{\"type\":\"trafficlights\",\"cost\":" << traffic_signal_penalty/10. << "},"; + dg_debug_turns_file << " \"geometry\":{\"type\":\"Point\",\"coordinates\":[" << std::setprecision(12) << nodeinfo.lon/COORDINATE_PRECISION << "," << nodeinfo.lat/COORDINATE_PRECISION << "]}}"; + dg_first_turn_debug = false; + } +} + +inline void DEBUG_UTURN( + const NodeID node, + const std::vector& m_node_info_list, + const int traffic_signal_penalty) +{ + if (dg_output_turn_debug) + { + const QueryNode &nodeinfo = m_node_info_list[node]; + if (!dg_first_turn_debug) dg_debug_turns_file << "," << std::endl; + dg_debug_turns_file << "{ \"type\":\"Feature\",\"properties\":{\"type\":\"trafficlights\",\"cost\":" << traffic_signal_penalty/10. << "},"; + dg_debug_turns_file << " \"geometry\":{\"type\":\"Point\",\"coordinates\":[" << std::setprecision(12) << nodeinfo.lon/COORDINATE_PRECISION << "," << nodeinfo.lat/COORDINATE_PRECISION << "]}}"; + dg_first_turn_debug = false; + } +} + + +inline void DEBUG_TURN( + const NodeID node, + const std::vector& m_node_info_list, + const FixedPointCoordinate & first_coordinate, + const int turn_angle, + const int turn_penalty) +{ + if (turn_penalty > 0 && dg_output_turn_debug) + { + const QueryNode &v = m_node_info_list[node]; + + const float bearing_uv = coordinate_calculation::bearing(first_coordinate,v); + float uvw_normal = bearing_uv + turn_angle/2; + while (uvw_normal >= 360.) { uvw_normal -= 360.; } + + if (!dg_first_turn_debug) dg_debug_turns_file << "," << std::endl; + dg_debug_turns_file << "{ \"type\":\"Feature\",\"properties\":{\"type\":\"turn\",\"cost\":" << turn_penalty/10. << ",\"turn_angle\":" << static_cast(turn_angle) << ",\"normal\":" << static_cast(uvw_normal) << "},"; + dg_debug_turns_file << " \"geometry\":{\"type\":\"Point\",\"coordinates\":[" << std::setprecision(12) << v.lon/COORDINATE_PRECISION << "," << v.lat/COORDINATE_PRECISION << "]}}"; + dg_first_turn_debug = false; + } +} + +inline void DEBUG_TURNS_STOP() +{ + if (dg_output_turn_debug) + { + dg_debug_turns_file << std::endl << "]}" << std::endl; + dg_debug_turns_file.close(); + } +} + +#endif // DEBUG_GEOMETRY + + +#endif // DEBUG_GEOMETRY_H