diff --git a/CMakeLists.txt b/CMakeLists.txt index da2b4123c4..5ee880a045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -279,7 +279,7 @@ set(valhalla_programs valhalla_run_map_match valhalla_benchmark_loki valhalla_be set(valhalla_data_tools valhalla_build_statistics valhalla_ways_to_edges valhalla_validate_transit valhalla_benchmark_admins valhalla_build_connectivity valhalla_build_tiles valhalla_build_admins valhalla_convert_transit valhalla_ingest_transit valhalla_query_transit valhalla_add_predicted_traffic - valhalla_assign_speeds valhalla_add_elevation valhalla_build_landmarks valhalla_add_landmarks) + valhalla_assign_speeds valhalla_add_elevation valhalla_build_landmarks valhalla_add_landmarks valhalla_print_tile) ## Valhalla services set(valhalla_services valhalla_loki_worker valhalla_odin_worker valhalla_thor_worker) diff --git a/src/baldr/graphtileheader.cc b/src/baldr/graphtileheader.cc index 82ba791f70..a1cd68b0c7 100644 --- a/src/baldr/graphtileheader.cc +++ b/src/baldr/graphtileheader.cc @@ -2,6 +2,8 @@ #include "config.h" #include +#include +#include using namespace valhalla::baldr; @@ -87,5 +89,93 @@ std::pair GraphTileHeader::bin_offset(size_t index) const { throw std::runtime_error("Bin out of bounds"); } +std::string GraphTileHeader::debug_string() const { + std::ostringstream os; + os.setf(std::ios::boolalpha); + + // Bitfields (graphid/quality/flags) + os << "graphid_: " << static_cast(graphid_) << "\n"; + os << "density_: " << static_cast(density_) << "\n"; + os << "name_quality_: " << static_cast(name_quality_) << "\n"; + os << "speed_quality_: " << static_cast(speed_quality_) << "\n"; + os << "exit_quality_: " << static_cast(exit_quality_) << "\n"; + os << "has_elevation_: " << static_cast(has_elevation_) << "\n"; + os << "has_ext_directededge_: " << static_cast(has_ext_directededge_) << "\n"; + + // Base LL + os << "base_ll_.first (lng): " << base_ll_.first << "\n"; + os << "base_ll_.second (lat): " << base_ll_.second << "\n"; + + // Version and dataset id + os << "version_: " << version_.data() << "\n"; + os << "dataset_id_: " << static_cast(dataset_id_) << "\n"; + + // Record counts (bitfields) + os << "nodecount_: " << static_cast(nodecount_) << "\n"; + os << "directededgecount_: " << static_cast(directededgecount_) << "\n"; + os << "predictedspeeds_count_: " << static_cast(predictedspeeds_count_) << "\n"; + os << "spare1_: " << static_cast(spare1_) << "\n"; + + // Mixed-width counts & spares + os << "transitioncount_: " << static_cast(transitioncount_) << "\n"; + os << "spare3_: " << static_cast(spare3_) << "\n"; + os << "turnlane_count_: " << static_cast(turnlane_count_) << "\n"; + os << "spare4_: " << static_cast(spare4_) << "\n"; + os << "transfercount_: " << static_cast(transfercount_) << "\n"; + os << "spare2_: " << static_cast(spare2_) << "\n"; + + // Transit counts + os << "departurecount_: " << static_cast(departurecount_) << "\n"; + os << "stopcount_: " << static_cast(stopcount_) << "\n"; + os << "spare5_: " << static_cast(spare5_) << "\n"; + os << "routecount_: " << static_cast(routecount_) << "\n"; + os << "schedulecount_: " << static_cast(schedulecount_) << "\n"; + + // More counts + os << "signcount_: " << static_cast(signcount_) << "\n"; + os << "spare6_: " << static_cast(spare6_) << "\n"; + os << "access_restriction_count_: " << static_cast(access_restriction_count_) << "\n"; + os << "admincount_: " << static_cast(admincount_) << "\n"; + os << "spare7_: " << static_cast(spare7_) << "\n"; + + // Spare words + os << "spareword0_: " << static_cast(spareword0_) << "\n"; + os << "spareword1_: " << static_cast(spareword1_) << "\n"; + + // Offsets (variable-size sections) + os << "complex_restriction_forward_offset_: " << complex_restriction_forward_offset_ << "\n"; + os << "complex_restriction_reverse_offset_: " << complex_restriction_reverse_offset_ << "\n"; + os << "edgeinfo_offset_: " << edgeinfo_offset_ << "\n"; + os << "textlist_offset_: " << textlist_offset_ << "\n"; + + // Date created + os << "date_created_: " << date_created_ << "\n"; + + // Bin offsets + os << "bin_offsets_: ["; + for (size_t i = 0; i < bin_offsets_.size(); ++i) { + os << bin_offsets_[i]; + if (i + 1 < bin_offsets_.size()) os << ", "; + } + os << "]\n"; + + // Lane connectivity and predicted speeds offsets + os << "lane_connectivity_offset_: " << lane_connectivity_offset_ << "\n"; + os << "predictedspeeds_offset_: " << predictedspeeds_offset_ << "\n"; + + // Tile size + os << "tile_size_: " << tile_size_ << "\n"; + + // Empty slots + os << "empty_slots_: ["; + for (size_t i = 0; i < empty_slots_.size(); ++i) { + os << empty_slots_[i]; + if (i + 1 < empty_slots_.size()) os << ", "; + } + os << "]\n"; + + return os.str(); +} + } // namespace baldr } // namespace valhalla diff --git a/src/baldr/nodeinfo.cc b/src/baldr/nodeinfo.cc index c30722cfe2..e8a9931941 100644 --- a/src/baldr/nodeinfo.cc +++ b/src/baldr/nodeinfo.cc @@ -4,6 +4,9 @@ #include "baldr/rapidjson_utils.h" #include "midgard/logging.h" +#include +#include + using namespace valhalla::midgard; using namespace valhalla::baldr; @@ -78,6 +81,49 @@ NodeInfo::NodeInfo(const PointLL& tile_corner, set_cash_only_toll(cash_only_toll); } +std::string NodeInfo::debug_string() const { + std::ostringstream os; + os.setf(std::ios::boolalpha); + + // 1st 8-byte word + os << "lat_offset_: " << static_cast(lat_offset_) << "\n"; + os << "lat_offset7_: " << static_cast(lat_offset7_) << "\n"; + os << "lon_offset_: " << static_cast(lon_offset_) << "\n"; + os << "lon_offset7_: " << static_cast(lon_offset7_) << "\n"; + os << "access_: " << static_cast(access_) << "\n"; + + // 2nd 8-byte word + os << "edge_index_: " << static_cast(edge_index_) << "\n"; + os << "edge_count_: " << static_cast(edge_count_) << "\n"; + os << "admin_index_: " << static_cast(admin_index_) << "\n"; + os << "timezone_: " << static_cast(timezone_) << "\n"; + os << "intersection_: " << static_cast(intersection_) << "\n"; + os << "type_: " << static_cast(type_) << "\n"; + os << "density_: " << static_cast(density_) << "\n"; + os << "traffic_signal_: "<< static_cast(traffic_signal_) << "\n"; + os << "mode_change_: " << static_cast(mode_change_) << "\n"; + os << "named_: " << static_cast(named_) << "\n"; + + // 3rd 8-byte word + os << "transition_index_: " << static_cast(transition_index_) << "\n"; + os << "transition_count_: " << static_cast(transition_count_) << "\n"; + os << "local_driveability_: " << static_cast(local_driveability_) << "\n"; + os << "local_edge_count_: " << static_cast(local_edge_count_) << "\n"; + os << "drive_on_right_: " << static_cast(drive_on_right_) << "\n"; + os << "tagged_access_: " << static_cast(tagged_access_) << "\n"; + os << "private_access_: " << static_cast(private_access_) << "\n"; + os << "cash_only_toll_: " << static_cast(cash_only_toll_) << "\n"; + os << "elevation_: " << static_cast(elevation_) << "\n"; + os << "timezone_ext_1_: " << static_cast(timezone_ext_1_) << "\n"; + // If you ever enable timezone_ext_2_, add it here. + os << "spare2_: " << static_cast(spare2_) << "\n"; + + // 4th 8-byte word (raw headings / transit-connection storage) + os << "headings_: " << static_cast(headings_) << "\n"; + + return os.str(); +} + // Sets the latitude and longitude. void NodeInfo::set_latlng(const PointLL& tile_corner, const PointLL& ll) { // Protect against a node being slightly outside the tile (due to float roundoff) diff --git a/src/mjolnir/valhalla_print_tile.cc b/src/mjolnir/valhalla_print_tile.cc new file mode 100644 index 0000000000..e119af1f30 --- /dev/null +++ b/src/mjolnir/valhalla_print_tile.cc @@ -0,0 +1,274 @@ +#include "argparse_utils.h" +#include "baldr/graphreader.h" +#include "baldr/graphtile.h" +#include "baldr/directededge.h" +#include "baldr/nodeinfo.h" +#include "baldr/nodetransition.h" +#include "baldr/accessrestriction.h" +#include "baldr/admin.h" +#include "baldr/sign.h" +#include "baldr/turnlanes.h" +#include "baldr/laneconnectivity.h" +#include "midgard/logging.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace valhalla::baldr; +using namespace valhalla::midgard; + +void print_tile_info(const GraphTile* tile) { + if (!tile) { + std::cout << "Tile not found or empty" << std::endl; + return; + } + + const auto* header = tile->header(); + std::cout << "=== Tile Header ===" << std::endl; + std::cout << "GraphId: 0x" << std::hex << tile->id().value << std::dec << std::endl; + std::cout << header->debug_string() << std::endl; + std::cout << std::endl; + + // Print nodes + std::cout << "=== Nodes (" << header->nodecount() << ") ===" << std::endl; + for (uint32_t i = 0; i < header->nodecount(); i++) { + const auto* node = tile->node(i); + std::cout << "\nNode " << i << ":" << std::endl; + std::cout << node->debug_string() << std::endl; + } + std::cout << std::endl; + + // Print directed edges with raw words and edgeinfo + std::cout << "=== Directed Edges (" << header->directededgecount() << ") ===" << std::endl; + for (uint32_t i = 0; i < header->directededgecount(); i++) { + const auto* edge = tile->directededge(i); + std::cout << "\nEdge " << i << ":" << std::endl; + + // Print raw 64-bit words for debugging + const auto* words = reinterpret_cast(edge); + std::cout << " Raw words: "; + for (int w = 0; w < 6; w++) { + std::cout << "0x" << std::hex << std::setw(16) << std::setfill('0') << words[w] << " "; + } + std::cout << std::dec << std::endl; + + std::cout << edge->debug_string() << std::endl; + + // Print edgeinfo + auto edgeinfo = tile->edgeinfo(edge); + std::cout << " EdgeInfo:" << std::endl; + std::cout << " wayid: " << edgeinfo.wayid() << std::endl; + std::cout << " name_count: " << edgeinfo.name_count() << std::endl; + auto names = edgeinfo.GetNames(); + for (size_t n = 0; n < names.size(); n++) { + std::cout << " name[" << n << "]: " << names[n] << std::endl; + } + std::cout << " encoded_shape_size: " << edgeinfo.encoded_shape_size() << std::endl; + auto encoded_shape = edgeinfo.encoded_shape(); + std::cout << " encoded_shape_hex: "; + for (char c : encoded_shape) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (static_cast(static_cast(c))) << " "; + } + std::cout << std::dec << std::endl; + std::cout << " mean_elevation: " << edgeinfo.mean_elevation() << std::endl; + std::cout << " speed_limit: " << edgeinfo.speed_limit() << std::endl; + } + std::cout << std::endl; + + // Print directed edge extensions (disabled - crashes) + // if (header->has_ext_directededge()) { + // std::cout << "=== Directed Edge Extensions ===" << std::endl; + // } + + // Print node transitions + if (header->transitioncount() > 0) { + std::cout << "=== Node Transitions (" << header->transitioncount() << ") ===" << std::endl; + for (uint32_t i = 0; i < header->transitioncount(); i++) { + const auto* trans = tile->transition(i); + std::cout << "\nTransition " << i << ":" << std::endl; + std::cout << trans->debug_string() << std::endl; + } + std::cout << std::endl; + } + + // Print access restrictions + if (header->access_restriction_count() > 0) { + std::cout << "=== Access Restrictions (" << header->access_restriction_count() << ") ===" << std::endl; + for (uint32_t i = 0; i < header->directededgecount(); i++) { + auto restrictions = tile->GetAccessRestrictions(i, kAllAccess); + if (!restrictions.empty()) { + std::cout << "\nEdge " << i << " restrictions:" << std::endl; + for (const auto& r : restrictions) { + std::cout << " type: " << static_cast(r.type()) << ", value: " << r.value() << ", modes: " << r.modes() << std::endl; + } + } + } + std::cout << std::endl; + } + + // Print admins + if (header->admincount() > 0) { + std::cout << "=== Admins (" << header->admincount() << ") ===" << std::endl; + for (size_t i = 0; i < header->admincount(); i++) { + const auto* admin = tile->admin(i); + if (admin) { + std::cout << "\nAdmin " << i << ":" << std::endl; + std::cout << admin->debug_string() << std::endl; + } + } + std::cout << std::endl; + } + + // Print signs + if (header->signcount() > 0) { + std::cout << "=== Signs (" << header->signcount() << ") ===" << std::endl; + for (uint32_t i = 0; i < header->directededgecount(); i++) { + const auto* edge = tile->directededge(i); + if (edge->sign()) { + auto signs = tile->GetSigns(i); + if (!signs.empty()) { + std::cout << "\nEdge " << i << " signs:" << std::endl; + for (const auto& s : signs) { + std::cout << " type: " << static_cast(s.type()) << ", text: " << s.text() << std::endl; + } + } + } + } + std::cout << std::endl; + } + + // Print turn lanes + if (header->turnlane_count() > 0) { + std::cout << "=== Turn Lanes (" << header->turnlane_count() << ") ===" << std::endl; + for (uint32_t i = 0; i < header->directededgecount(); i++) { + auto lanes = tile->turnlanes(i); + if (!lanes.empty()) { + std::cout << "\nEdge " << i << " turn lanes: "; + for (auto mask : lanes) { + std::cout << mask << " "; + } + std::cout << std::endl; + } + } + std::cout << std::endl; + } + + // Print signs + if (header->signcount() > 0) { + std::cout << "=== Signs (" << header->signcount() << ") ===" << std::endl; + std::cout << "Sign data present" << std::endl; + std::cout << std::endl; + } + + // Print complex restrictions (use offsets as indicators) + if (header->complex_restriction_forward_offset() > 0 || header->complex_restriction_reverse_offset() > 0) { + std::cout << "=== Complex Restrictions ===" << std::endl; + std::cout << "Forward offset: " << header->complex_restriction_forward_offset() << std::endl; + std::cout << "Reverse offset: " << header->complex_restriction_reverse_offset() << std::endl; + std::cout << std::endl; + } + + // Print lane connectivity + if (header->lane_connectivity_offset() > 0) { + std::cout << "=== Lane Connectivity ===" << std::endl; + for (uint32_t i = 0; i < header->directededgecount(); i++) { + auto connectivity = tile->GetLaneConnectivity(i); + if (!connectivity.empty()) { + std::cout << "\nEdge " << i << " lane connectivity:" << std::endl; + for (const auto& lc : connectivity) { + std::cout << " from: " << lc.from() << ", to: " << lc.to() << ", to_lanes: " << lc.to_lanes() << ", from_lanes: " << lc.from_lanes() << std::endl; + } + } + } + std::cout << std::endl; + } +} + +int main(int argc, char** argv) { + // Disable logging output to keep stdout clean for diffing + logging::Configure({{"type", ""}}); + + const auto program = std::filesystem::path(__FILE__).stem().string(); + + try { + cxxopts::Options options( + program, + program + " " + VALHALLA_PRINT_VERSION + "\n\n" + "Print structured information about a Valhalla tile\n"); + + options.add_options() + ("h,help", "Print this help message.") + ("v,version", "Print the version of this software.") + ("c,config", "Path to the configuration file", cxxopts::value()) + ("t,tile", "Tile ID (in GraphId format, e.g., 0x1187D218 or decimal)", cxxopts::value()) + ("f,file", "Direct path to tile file (.gph)", cxxopts::value()); + + auto result = options.parse(argc, argv); + + if (result.count("help")) { + std::cout << options.help() << std::endl; + return EXIT_SUCCESS; + } + + if (result.count("version")) { + std::cout << program << " " << VALHALLA_PRINT_VERSION << std::endl; + return EXIT_SUCCESS; + } + + boost::property_tree::ptree config; + + if (result.count("file")) { + // Read tile directly from file + std::string tile_file = result["file"].as(); + // For direct file reading, use a dummy GraphId and load the file + std::ifstream ifs(tile_file, std::ios::binary); + if (!ifs) { + throw std::runtime_error("Cannot open file: " + tile_file); + } + ifs.seekg(0, std::ios::end); + size_t size = ifs.tellg(); + ifs.seekg(0, std::ios::beg); + std::vector data(size); + ifs.read(data.data(), size); + auto tile = GraphTile::Create(GraphId(), std::move(data)); + print_tile_info(tile.get()); + } else if (result.count("config") && result.count("tile")) { + // Read tile via GraphReader + if (!parse_common_args(program, options, result, &config, "mjolnir.logging")) + return EXIT_SUCCESS; + + std::string tile_str = result["tile"].as(); + uint64_t tile_id_val; + if (tile_str.substr(0, 2) == "0x" || tile_str.substr(0, 2) == "0X") { + tile_id_val = std::stoull(tile_str, nullptr, 16); + } else { + tile_id_val = std::stoull(tile_str); + } + + GraphId tile_id(tile_id_val); + GraphReader reader(config.get_child("mjolnir")); + auto tile = reader.GetGraphTile(tile_id); + print_tile_info(tile.get()); + } else { + std::cerr << "Either --file or both --config and --tile must be specified\n\n"; + std::cout << options.help() << std::endl; + return EXIT_FAILURE; + } + + } catch (cxxopts::exceptions::exception& e) { + std::cerr << e.what() << std::endl; + return EXIT_FAILURE; + } catch (std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/valhalla/baldr/admin.h b/valhalla/baldr/admin.h index 9a8f88cefc..eb37fe9c4f 100644 --- a/valhalla/baldr/admin.h +++ b/valhalla/baldr/admin.h @@ -3,6 +3,7 @@ #include #include +#include #include namespace valhalla { @@ -60,6 +61,18 @@ class Admin { */ uint32_t country_offset() const; + /** + * Returns a string for debugging. + */ + std::string debug_string() const { + std::ostringstream os; + os << "country_offset_: " << country_offset_ << "\n"; + os << "state_offset_: " << state_offset_ << "\n"; + os << "country_iso_: " << country_iso() << "\n"; + os << "state_iso_: " << state_iso() << "\n"; + return os.str(); + } + protected: uint32_t country_offset_; // country name offset uint32_t state_offset_; // state name offset diff --git a/valhalla/baldr/directededge.h b/valhalla/baldr/directededge.h index 8e4714ad87..16f0a574de 100644 --- a/valhalla/baldr/directededge.h +++ b/valhalla/baldr/directededge.h @@ -6,6 +6,9 @@ #include #include +#include +#include + namespace valhalla { namespace baldr { @@ -1205,6 +1208,103 @@ class DirectedEdge { */ void json(rapidjson::writer_wrapper_t& writer) const; + /** + * Returns a multi-line string of all internal bitfield properties and their values. + * Each line is "name: value". Intended for debugging/inspection. + */ + std::string debug_string() const { + std::ostringstream os; + os.setf(std::ios::boolalpha); + + // 1st 8-byte word + os << "endnode_: " << static_cast(endnode_) << "\n"; + os << "restrictions_: " << static_cast(restrictions_) << "\n"; + os << "opp_index_: " << static_cast(opp_index_) << "\n"; + os << "forward_: " << static_cast(forward_) << "\n"; + os << "leaves_tile_: " << static_cast(leaves_tile_) << "\n"; + os << "ctry_crossing_: " << static_cast(ctry_crossing_) << "\n"; + + // 2nd 8-byte word + os << "edgeinfo_offset_: " << static_cast(edgeinfo_offset_) << "\n"; + os << "access_restriction_: " << static_cast(access_restriction_) << "\n"; + os << "start_restriction_: " << static_cast(start_restriction_) << "\n"; + os << "end_restriction_: " << static_cast(end_restriction_) << "\n"; + os << "complex_restriction_: " << static_cast(complex_restriction_) << "\n"; + os << "dest_only_: " << static_cast(dest_only_) << "\n"; + os << "not_thru_: " << static_cast(not_thru_) << "\n"; + + // 3rd 8-byte word + os << "speed_: " << static_cast(speed_) << "\n"; + os << "free_flow_speed_: " << static_cast(free_flow_speed_) << "\n"; + os << "constrained_flow_speed_: " << static_cast(constrained_flow_speed_) << "\n"; + os << "truck_speed_: " << static_cast(truck_speed_) << "\n"; + os << "name_consistency_: " << static_cast(name_consistency_) << "\n"; + os << "use_: " << static_cast(use_) << "\n"; + os << "lanecount_: " << static_cast(lanecount_) << "\n"; + os << "density_: " << static_cast(density_) << "\n"; + os << "classification_: " << static_cast(classification_) << "\n"; + os << "surface_: " << static_cast(surface_) << "\n"; + os << "toll_: " << static_cast(toll_) << "\n"; + os << "roundabout_: " << static_cast(roundabout_) << "\n"; + os << "truck_route_: " << static_cast(truck_route_) << "\n"; + os << "has_predicted_speed_: " << static_cast(has_predicted_speed_) << "\n"; + + // 4th 8-byte word + os << "forwardaccess_: " << static_cast(forwardaccess_) << "\n"; + os << "reverseaccess_: " << static_cast(reverseaccess_) << "\n"; + os << "max_up_slope_: " << static_cast(max_up_slope_) << "\n"; + os << "max_down_slope_: " << static_cast(max_down_slope_) << "\n"; + os << "sac_scale_: " << static_cast(sac_scale_) << "\n"; + os << "cycle_lane_: " << static_cast(cycle_lane_) << "\n"; + os << "bike_network_: " << static_cast(bike_network_) << "\n"; + os << "use_sidepath_: " << static_cast(use_sidepath_) << "\n"; + os << "dismount_: " << static_cast(dismount_) << "\n"; + os << "sidewalk_left_: " << static_cast(sidewalk_left_) << "\n"; + os << "sidewalk_right_: " << static_cast(sidewalk_right_) << "\n"; + os << "shoulder_: " << static_cast(shoulder_) << "\n"; + os << "lane_conn_: " << static_cast(lane_conn_) << "\n"; + os << "turnlanes_: " << static_cast(turnlanes_) << "\n"; + os << "sign_: " << static_cast(sign_) << "\n"; + os << "internal_: " << static_cast(internal_) << "\n"; + os << "tunnel_: " << static_cast(tunnel_) << "\n"; + os << "bridge_: " << static_cast(bridge_) << "\n"; + os << "traffic_signal_: " << static_cast(traffic_signal_) << "\n"; + os << "spare1_: " << static_cast(spare1_) << "\n"; + os << "deadend_: " << static_cast(deadend_) << "\n"; + os << "bss_connection_: " << static_cast(bss_connection_) << "\n"; + os << "stop_sign_: " << static_cast(stop_sign_) << "\n"; + os << "yield_sign_: " << static_cast(yield_sign_) << "\n"; + os << "hov_type_: " << static_cast(hov_type_) << "\n"; + os << "indoor_: " << static_cast(indoor_) << "\n"; + os << "lit_: " << static_cast(lit_) << "\n"; + os << "dest_only_hgv_: " << static_cast(dest_only_hgv_) << "\n"; + os << "spare4_: " << static_cast(spare4_) << "\n"; + + // 5th 8-byte word + os << "turntype_: " << static_cast(turntype_) << "\n"; + os << "edge_to_left_: " << static_cast(edge_to_left_) << "\n"; + os << "length_: " << static_cast(length_) << "\n"; + os << "weighted_grade_: " << static_cast(weighted_grade_) << "\n"; + os << "curvature_: " << static_cast(curvature_) << "\n"; + + // Stop impact / line + os << "stopimpact_.s.stopimpact: " << static_cast(stopimpact_.s.stopimpact) << "\n"; + os << "stopimpact_.s.edge_to_right: " << static_cast(stopimpact_.s.edge_to_right) << "\n"; + os << "stopimpact_.lineid: " << static_cast(stopimpact_.lineid) << "\n"; + + // 6th 8-byte word (u32 bitfield) + os << "localedgeidx_: " << static_cast(localedgeidx_) << "\n"; + os << "opp_local_idx_: " << static_cast(opp_local_idx_) << "\n"; + os << "shortcut_: " << static_cast(shortcut_) << "\n"; + os << "superseded_: " << static_cast(superseded_) << "\n"; + os << "is_shortcut_: " << static_cast(is_shortcut_) << "\n"; + os << "speed_type_: " << static_cast(speed_type_) << "\n"; + os << "named_: " << static_cast(named_) << "\n"; + os << "link_: " << static_cast(link_) << "\n"; + + return os.str(); + } + protected: // 1st 8-byte word uint64_t endnode_ : 46; // End node of the directed edge @@ -1314,6 +1414,16 @@ class DirectedEdge { */ class DirectedEdgeExt { +public: + /** + * Returns a string for debugging. + */ + std::string debug_string() const { + std::ostringstream os; + os << "spare0_: 0x" << std::hex << spare0_ << std::dec << "\n"; + return os.str(); + } + protected: uint64_t spare0_ : 64; }; diff --git a/valhalla/baldr/graphtileheader.h b/valhalla/baldr/graphtileheader.h index 5d154e16c8..6ecb2d73ba 100644 --- a/valhalla/baldr/graphtileheader.h +++ b/valhalla/baldr/graphtileheader.h @@ -589,6 +589,8 @@ class GraphTileHeader { tile_size_ = offset; } + std::string debug_string() const; + protected: // TODO when c++20 bitfields can be initialized here // GraphId (tileid and level) of this tile. Data quality metrics. diff --git a/valhalla/baldr/nodeinfo.h b/valhalla/baldr/nodeinfo.h index b5b04fa486..a6efdc21d8 100644 --- a/valhalla/baldr/nodeinfo.h +++ b/valhalla/baldr/nodeinfo.h @@ -494,6 +494,8 @@ class NodeInfo { */ void json(const graph_tile_ptr& tile, rapidjson::writer_wrapper_t& writer) const; + std::string debug_string() const; + protected: // Organized into 8-byte words so structure will align to 8 byte boundaries. diff --git a/valhalla/baldr/nodetransition.h b/valhalla/baldr/nodetransition.h index 445778e5d3..8402f970c5 100644 --- a/valhalla/baldr/nodetransition.h +++ b/valhalla/baldr/nodetransition.h @@ -3,6 +3,9 @@ #include +#include +#include + namespace valhalla { namespace baldr { @@ -46,6 +49,17 @@ class NodeTransition { return up_; } + /** + * Returns a string for debugging. + */ + std::string debug_string() const { + std::ostringstream os; + os << "endnode_: " << GraphId(endnode_) << "\n"; + os << "up_: " << static_cast(up_) << "\n"; + os << "spare_: " << spare_ << "\n"; + return os.str(); + } + protected: uint64_t endnode_ : 46; uint64_t up_ : 1;