void create_single_way(const osmium::Way &way) { osmium::geom::OGRFactory<> ogr_factory; OGRLineString *linestring = nullptr; try { linestring = ogr_factory.create_linestring(way, osmium::geom::use_nodes::unique, osmium::geom::direction::forward).release(); } catch (osmium::geometry_error) { insert_way_error(way); return; } catch (...) { cerr << "Error at way: " << way.id() << endl; cerr << " Unexpected error" << endl; return; } try { ds.insert_way_feature(linestring, way, 0); } catch (osmium::geometry_error&) { cerr << "Inserting to table failed for way: " << way.id() << endl; } catch (...) { cerr << "Inserting to table failed for way: " << way.id() << endl; cerr << " Unexpected error" << endl; } delete linestring; }
void output_pgsql_t::pgsql_out_way(osmium::Way const &way, taglist_t *tags, bool polygon, bool roads) { if (polygon && way.is_closed()) { auto wkb = m_builder.get_wkb_polygon(way); if (!wkb.empty()) { expire.from_wkb(wkb.c_str(), way.id()); if (m_enable_way_area) { char tmp[32]; auto const area = m_options.reproject_area ? ewkb::parser_t(wkb).get_area<reprojection>( m_options.projection.get()) : ewkb::parser_t(wkb) .get_area<osmium::geom::IdentityProjection>(); snprintf(tmp, sizeof(tmp), "%g", area); tags->push_override(tag_t("way_area", tmp)); } m_tables[t_poly]->write_row(way.id(), *tags, wkb); } } else { double const split_at = m_options.projection->target_latlon() ? 1 : 100 * 1000; for (auto const &wkb : m_builder.get_wkb_line(way.nodes(), split_at)) { expire.from_wkb(wkb.c_str(), way.id()); m_tables[t_line]->write_row(way.id(), *tags, wkb); if (roads) { m_tables[t_roads]->write_row(way.id(), *tags, wkb); } } } }
void way(const osmium::Way& way) { // detect a new way if (current_way_id != 0 && current_way_id != way.id()) { write_way_extra_nodes(); current_way_nodes.clear(); } current_way_id = way.id(); if (debug) { std::cerr << "softcut way " << way.id() << " v" << way.version() << "\n"; } for (const auto& node_ref : way.nodes()) { current_way_nodes.insert(node_ref.ref()); } for (const auto& extract : info->extracts) { for (const auto& node_ref : way.nodes()) { if (extract->node_tracker.get(node_ref.ref())) { if (debug) { std::cerr << "way has a node (" << node_ref.ref() << ") inside extract, recording in way_tracker\n"; } extract->way_tracker.set(way.id()); break; } } } }
void way(const osmium::Way& way) { try { gdalcpp::Feature feature{m_layer_linestring, m_factory.create_linestring(way)}; feature.set_field("id", int32_t(way.id())); add_feature(feature, way); } catch (const osmium::geometry_error&) { std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; } }
// - walk over all way-versions // - walk over all bboxes // - if the way-id is recorded in the bboxes way-trackers // - send the way to the bboxes writer void way(const osmium::Way& way) { if (debug) { std::cerr << "cut_administrative way " << way.id() << " v" << way.version() << "\n"; } for (const auto& extract : info->extracts) { if (extract->way_tracker.get(way.id())){ extract->write(way); } } }
void way(const osmium::Way& way) { if (m_max_relation_id > 0) { throw std::runtime_error("Found a way after a relation."); } if (m_max_way_id >= way.id()) { throw std::runtime_error("Way IDs out of order."); } m_max_way_id = way.id(); }
void way(const osmium::Way& way) { if (m_max_relation_id > std::numeric_limits<osmium::object_id_type>::min()) { throw out_of_order_error{"Found a way after a relation.", way.id()}; } if (m_max_way_id == way.id()) { throw out_of_order_error{"Way ID twice in input. Maybe you are using a history or change file?", way.id()}; } if (id_order{}(way.id(), m_max_way_id)) { throw out_of_order_error{"Way IDs out of order.", way.id()}; } m_max_way_id = way.id(); }
void parse_osmium_t::way(osmium::Way& way) { if (way.deleted()) { m_data->way_delete(way.id()); } else { if (m_append) { m_data->way_modify(way); } else { m_data->way_add(way); } } m_stats.add_way(way.id()); }
// - walk over all way-versions // - walk over all bboxes // - if the way-id is recorded in the bboxes way-trackers // - send the way to the bboxes writer void way(const osmium::Way& way) { if (debug) { std::cerr << "cut_administrative way " << way.id() << " v" << way.version() << "\n"; } for (const auto& extract : info->extracts) { if (extract->way_tracker.get(way.id())){ for (const auto& node_ref : way.nodes()) { if (!extract->node_tracker.get(node_ref.ref())) { extract->node_tracker.set(node_ref.ref()); } } } } }
/** * Assemble an area from the given way. * The resulting area is put into the out_buffer. * * @returns false if there was some kind of error building the * area, true otherwise. */ bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) { if (!config().create_way_polygons) { return true; } if (config().problem_reporter) { config().problem_reporter->set_object(osmium::item_type::way, way.id()); config().problem_reporter->set_nodes(way.nodes().size()); } // Ignore (but count) ways without segments. if (way.nodes().size() < 2) { ++stats().short_ways; return false; } if (!way.ends_have_same_id()) { ++stats().duplicate_nodes; if (config().problem_reporter) { config().problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location()); } } ++stats().from_ways; stats().invalid_locations = segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way); if (!config().ignore_invalid_locations && stats().invalid_locations > 0) { return false; } if (config().debug_level > 0) { std::cerr << "\nAssembling way " << way.id() << " containing " << segment_list().size() << " nodes\n"; } // Now create the Area object and add the attributes and tags // from the way. const bool okay = create_area(out_buffer, way); if (okay) { out_buffer.commit(); } else { out_buffer.rollback(); } if (debug()) { std::cerr << "Done: " << stats() << "\n"; } return okay; }
void way(const osmium::Way& way) { m_length += osmium::geom::haversine::distance(way.nodes()); try { std::unique_ptr<OGRLineString> ogrlinestring = m_factory.create_linestring(way); gdalcpp::Feature feature(m_layer_ways, std::move(ogrlinestring)); feature.set_field("way_id", std::to_string(way.id()).c_str()); feature.set_field("name", way.tags().get_value_by_key("name")); feature.set_field("source", way.tags().get_value_by_key("source")); const bool bogus = way.tags().has_tag("coastline", "bogus"); feature.set_field("bogus", bogus ? "t" : "f"); feature.add_to_layer(); } catch (const osmium::geometry_error&) { std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; } }
inline void parseWay(const osmium::Way& way) { const auto& tags = way.tags(); auto it = std::find_if(tags.begin(), tags.end(), highway_filter); if (it == tags.end()) { return; } const osmium::NodeRef& first = way.nodes().front(); const osmium::NodeRef& last = way.nodes().back(); // filter out closed ways, generally this will just cause false // positives with round-a-abouts if (first == last) { return; } const char* name = tags.get_value_by_key("name", ""); const char* ref = tags.get_value_by_key("ref", ""); unsigned name_id = getStringID(name); unsigned ref_id = getStringID(ref); // we can't use osmium ids because MultiMap expects unsigned keys unsigned long firstID = static_cast<unsigned long>(first.ref()); unsigned long lastID = static_cast<unsigned long>(last.ref()); const unsigned wayIdx = parsed_ways->size(); endpoint_way_map->unsorted_set(firstID, wayIdx); endpoint_way_map->unsorted_set(lastID, wayIdx); parsed_ways->emplace_back(way.id(), firstID, lastID, name_id, ref_id); }
uint32_t extract_segments_from_way_impl(osmium::area::ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Way& way, role_type role) { uint32_t invalid_locations = 0; osmium::NodeRef previous_nr; for (const osmium::NodeRef& nr : way.nodes()) { if (!nr.location().valid()) { ++invalid_locations; if (problem_reporter) { problem_reporter->report_invalid_location(way.id(), nr.ref()); } continue; } if (previous_nr.location()) { if (previous_nr.location() != nr.location()) { m_segments.emplace_back(previous_nr, nr, role, &way); } else { ++duplicate_nodes; if (problem_reporter) { problem_reporter->report_duplicate_node(previous_nr.ref(), nr.ref(), nr.location()); } } } previous_nr = nr; } return invalid_locations; }
polygon_type create_polygon(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir = direction::forward) { try { return create_polygon(way.nodes(), un, dir); } catch (osmium::geometry_error& e) { e.set_id("way", way.id()); throw; } }
int osmdata_t::way_modify(osmium::Way const &way) { idlist_t nodes(way.nodes()); slim_middle_t *slim = dynamic_cast<slim_middle_t *>(mid.get()); slim->ways_delete(way.id()); slim->ways_set(way); int status = 0; for (auto& out: outs) { status |= out->way_modify(way); } slim->way_changed(way.id()); return status; }
void way(const osmium::Way& way) { try { std::unique_ptr<OGRLineString> ogr_linestring = m_ogr_factory.create_linestring(way); OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn()); feature->SetGeometry(ogr_linestring.get()); feature->SetField("id", static_cast<double>(way.id())); feature->SetField("type", way.tags().get_value_by_key("type")); if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) { std::cerr << "Failed to create feature.\n"; exit(1); } OGRFeature::DestroyFeature(feature); } catch (osmium::geometry_error&) { std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; } }
void way(const osmium::Way& way) { ++ways; if (!matches_user_filter(way)) return; ++uways; for (const auto& node : way.nodes()) { m_nodefile << way.id() << "\t" << way.version() << "\t" << node.ref() << std::endl; } }
void way(osmium::Way& w) { ++utak; osmium::WayNodeList& wnl = w.nodes(); std::vector<osmium::unsigned_object_id_type> nds; for( osmium::NodeRef& n : wnl ) { nds.emplace_back(n.ref()); } way_node_map[w.id()] = nds; nds.clear(); }
void way(const osmium::Way& way) { ++ways; if (!matches_user_filter(way)) return; ++uways; if (way.visible()==false) { m_wayfile << way.id() << "\t" << way.version() << "\t" << way.changeset() << "\t" << way.timestamp().to_iso() << "\t" << way.uid() << std::endl; } }
void way(const osmium::Way& way) { m_check_order.way(way); if (m_way_count == 0) { m_progress_bar.remove(); m_vout << "Reading ways...\n"; } ++m_way_count; if (m_check_relations) { set(osmium::item_type::way, way.id()); } for (const auto& node_ref : way.nodes()) { if (!get(osmium::item_type::node, node_ref.ref())) { ++m_missing_nodes_in_ways; if (m_show_ids) { std::cout << "n" << node_ref.ref() << " in w" << way.id() << "\n"; } } } }
void feed_way(const osmium::Way& way) { try { const char* street = way.tags().get_value_by_key("addr:street"); const char* housenumber = way.tags().get_value_by_key("addr:housenumber"); const char* full = way.tags().get_value_by_key("addr:full"); const char* conscriptionnumber = way.tags().get_value_by_key("addr:conscriptionnumber"); const char* housename = way.tags().get_value_by_key("addr:housename"); const char* place = way.tags().get_value_by_key("addr:place"); const char* postcode = way.tags().get_value_by_key("addr:postcode"); const char* flats = way.tags().get_value_by_key("addr:flats"); const char* door = way.tags().get_value_by_key("addr:door"); const char* unit = way.tags().get_value_by_key("addr:unit"); const char* floor = way.tags().get_value_by_key("addr:floor"); const char* city = way.tags().get_value_by_key("addr:city"); const char* country = way.tags().get_value_by_key("addr:country"); const char* hamlet = way.tags().get_value_by_key("addr:hamlet"); const char* suburb = way.tags().get_value_by_key("addr:suburb"); const char* district = way.tags().get_value_by_key("addr:district"); const char* subdistrict = way.tags().get_value_by_key("addr:subdistrict"); const char* province = way.tags().get_value_by_key("addr:province"); const char* region = way.tags().get_value_by_key("addr:region"); const char* state = way.tags().get_value_by_key("addr:state"); if (!way.is_closed() && (street || housenumber || full || conscriptionnumber || housename || place || postcode || flats || door || unit || floor || city || country || hamlet || suburb || district || subdistrict || province || region || state)) { std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way); OGRFeature* const feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn()); feature->SetGeometryDirectly(static_cast<OGRGeometry*>(ogr_linestring.release())); feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok? feature->SetField("lastchange", way.timestamp().to_iso().c_str()); create_feature(feature); } } catch (osmium::geometry_error& e) { catch_geometry_error(e, way); } }
std::unique_ptr<OGRPoint> centroid(const osmium::Way& way) { std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way); OGRPolygon polygon; polygon.addRing(static_cast<OGRLinearRing*>(ogr_linestring.get())); std::unique_ptr<OGRPoint> centroid(new OGRPoint); int ret = polygon.Centroid(centroid.get()); if (ret != OGRERR_NONE) { std::cerr << "Couldn't calculate centroid of way = " << way.id() << ".\n"; osmium::geometry_error e(std::string("Couldn't calculate centroid of way = ") + std::to_string(way.id()) + std::string(".\n")); throw e; return nullptr; } else { return centroid; } return nullptr; }
void middle_pgsql_t::ways_set(osmium::Way const &way) { copy_buffer.reserve(way.nodes().size() * 10 + way.tags().byte_size() + 100); bool copy = way_table->copyMode; char delim = copy ? '\t' : '\0'; // Three params: id, nodes, tags */ const char *paramValues[4] = { copy_buffer.c_str(), }; copy_buffer = std::to_string(way.id()); copy_buffer += delim; paramValues[1] = paramValues[0] + copy_buffer.size(); if (way.nodes().size() == 0) { copy_buffer += "{}"; } else { copy_buffer += "{"; for (auto const &n : way.nodes()) { copy_buffer += std::to_string(n.ref()); copy_buffer += ','; } copy_buffer[copy_buffer.size() - 1] = '}'; } copy_buffer += delim; if (way.tags().empty() && !out_options->extra_attributes) { paramValues[2] = nullptr; copy_buffer += "\\N"; } else { paramValues[2] = paramValues[0] + copy_buffer.size(); buffer_store_tags(way, out_options->extra_attributes, copy); } if (copy) { copy_buffer += '\n'; pgsql_CopyData(__FUNCTION__, way_table->sql_conn, copy_buffer); } else { buffer_correct_params(paramValues, 3); pgsql_execPrepared(way_table->sql_conn, "insert_way", 3, (const char * const *)paramValues, PGRES_COMMAND_OK); } }
void feed_way(const osmium::Way& way) { try { const char* building = way.tags().get_value_by_key("building"); if (building && way.is_closed()) { std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way); OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn()); OGRPolygon polygon; polygon.addRing(static_cast<OGRLinearRing*>(ogr_linestring.get())); feature->SetGeometry(static_cast<OGRGeometry*>(&polygon)); feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok? feature->SetField("lastchange", way.timestamp().to_iso().c_str()); create_feature(feature); } } catch (osmium::geom::geometry_error& e) { catch_geometry_error(e, way); } }
void feed_way(const osmium::Way& way) { try { const char* building = way.tags().get_value_by_key("building"); if (building && way.is_closed()) { const char* street = way.tags().get_value_by_key("addr:street"); const char* houseno = way.tags().get_value_by_key("addr:housenumber"); if (street || houseno) { std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way); OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn()); OGRPolygon polygon; polygon.addRing(static_cast<OGRLinearRing*>(ogr_linestring.get())); feature->SetGeometry(static_cast<OGRGeometry*>(&polygon)); feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok? feature->SetField("lastchange", way.timestamp().to_iso().c_str()); const char* postcode = way.tags().get_value_by_key("addr:postcode"); const char* city = way.tags().get_value_by_key("addr:city"); const char* country = way.tags().get_value_by_key("addr:country"); const char* fulladdr = way.tags().get_value_by_key("addr:full"); const char* place = way.tags().get_value_by_key("addr:place"); if (street) { feature->SetField("street" , street); } if (houseno) { feature->SetField("houseno" , houseno); } if (postcode) { feature->SetField("postcode", postcode); } if (city) { feature->SetField("city", city); } if (country) { feature->SetField("country", country); } if (fulladdr) { feature->SetField("fulladdr", fulladdr); } if (place) { feature->SetField("place", place); } create_feature(feature); } } } catch (osmium::geometry_error& e) { catch_geometry_error(e, way); } }
void way ( osmium::Way& way ) { const char* highway = way.tags() ["highway"]; if ( !highway ) return; // http://wiki.openstreetmap.org/wiki/Key:highway if ( !strcmp ( highway, "footway" ) || !strcmp ( highway, "cycleway" ) || !strcmp ( highway, "bridleway" ) || !strcmp ( highway, "steps" ) || !strcmp ( highway, "path" ) || !strcmp ( highway, "construction" ) ) return; onewayf = false; const char* oneway = way.tags() ["oneway"]; if ( oneway ) { onewayf = true; ++onewayc; } ++nOSM_ways; double way_length = osmium::geom::haversine::distance ( way.nodes() ); sum_highhway_length += way_length; int node_counter {0}; int unique_node_counter {0}; osmium::Location from_loc; osmium::unsigned_object_id_type vertex_old; for ( const osmium::NodeRef& nr : way.nodes() ) { osmium::unsigned_object_id_type vertex = nr.positive_ref(); way2nodes[way.id()].push_back ( vertex ); try { vert.get ( vertex ); } catch ( std::exception& e ) { vert.set ( vertex, 1 ); ++unique_node_counter; //waynode_locations.set ( vertex, nr.location() ); waynode_locations[vertex] = nr.location(); } if ( node_counter > 0 ) { if ( !edge ( vertex_old, vertex ) ) { alist[vertex_old].push_back ( vertex ); double edge_length = distance ( vertex_old, vertex ); palist[vertex_old].push_back ( edge_length / 3.0 ); if ( edge_length>max_edge_length ) max_edge_length = edge_length; mean_edge_length += edge_length; ++m_estimator; ++cedges; } else ++edge_multiplicity; if ( !onewayf ) { if ( !edge ( vertex, vertex_old ) ) { alist[vertex].push_back ( vertex_old ); double edge_length = distance ( vertex_old, vertex ); palist[vertex].push_back ( edge_length / 3.0 ); if ( edge_length>max_edge_length ) max_edge_length = edge_length; mean_edge_length += edge_length; ++m_estimator; ++cedges; } else ++edge_multiplicity; } } vertex_old = vertex; ++node_counter; } sum_highhway_nodes += node_counter; sum_unique_highhway_nodes += unique_node_counter; }
void report_inner_with_same_tags(const osmium::Way& way) override { header("inner way with same tags as relation or outer"); *m_out << "way_id=" << way.id() << '\n'; }
void report_way_in_multiple_rings(const osmium::Way& way) override { header("way in multiple rings"); *m_out << "way_id=" << way.id() << '\n'; }
/** * Takes the geometry contained in the ```input_way``` and the tags computed * by the lua profile inside ```parsed_way``` and computes all edge segments. * * Depending on the forward/backwards weights the edges are split into forward * and backward edges. * * warning: caller needs to take care of synchronization! */ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way) { if (((0 >= parsed_way.forward_speed) || (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) && ((0 >= parsed_way.backward_speed) || (TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) && (0 >= parsed_way.duration)) { // Only true if the way is specified by the speed profile return; } if (input_way.nodes().size() <= 1) { // safe-guard against broken data return; } if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id()) { util::SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << input_way.id() << " of size " << input_way.nodes().size(); return; } InternalExtractorEdge::WeightData forward_weight_data; InternalExtractorEdge::WeightData backward_weight_data; if (0 < parsed_way.duration) { const unsigned num_edges = (input_way.nodes().size() - 1); // FIXME We devide by the numer of nodes here, but should rather consider // the length of each segment. We would eigther have to compute the length // of the whole way here (we can't: no node coordinates) or push that back // to the container and keep a reference to the way. forward_weight_data.duration = parsed_way.duration / num_edges; forward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION; backward_weight_data.duration = parsed_way.duration / num_edges; backward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION; } else { if (parsed_way.forward_speed > 0 && parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE) { forward_weight_data.speed = parsed_way.forward_speed; forward_weight_data.type = InternalExtractorEdge::WeightType::SPEED; } if (parsed_way.backward_speed > 0 && parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE) { backward_weight_data.speed = parsed_way.backward_speed; backward_weight_data.type = InternalExtractorEdge::WeightType::SPEED; } } if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID && backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID) { util::SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << input_way.id(); return; } // FIXME this need to be moved into the profiles const char *data = input_way.get_value_by_key("highway"); guidance::RoadClassificationData road_classification; if (data) { road_classification.road_class = guidance::functionalRoadClassFromTag(data); } const auto laneStringToDescription = [](std::string lane_string) -> TurnLaneDescription { if (lane_string.empty()) return {}; TurnLaneDescription lane_description; typedef boost::tokenizer<boost::char_separator<char>> tokenizer; boost::char_separator<char> sep("|", "", boost::keep_empty_tokens); boost::char_separator<char> inner_sep(";", ""); tokenizer tokens(lane_string, sep); const constexpr std::size_t num_osm_tags = 11; const constexpr char *osm_lane_strings[num_osm_tags] = {"none", "through", "sharp_left", "left", "slight_left", "slight_right", "right", "sharp_right", "reverse", "merge_to_left", "merge_to_right"}; const constexpr TurnLaneType::Mask masks_by_osm_string[num_osm_tags + 1] = { TurnLaneType::none, TurnLaneType::straight, TurnLaneType::sharp_left, TurnLaneType::left, TurnLaneType::slight_left, TurnLaneType::slight_right, TurnLaneType::right, TurnLaneType::sharp_right, TurnLaneType::uturn, TurnLaneType::merge_to_left, TurnLaneType::merge_to_right, TurnLaneType::empty}; // fallback, if string not found for (auto iter = tokens.begin(); iter != tokens.end(); ++iter) { tokenizer inner_tokens(*iter, inner_sep); guidance::TurnLaneType::Mask lane_mask = inner_tokens.begin() == inner_tokens.end() ? TurnLaneType::none : TurnLaneType::empty; for (auto token_itr = inner_tokens.begin(); token_itr != inner_tokens.end(); ++token_itr) { auto position = std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr); const auto translated_mask = masks_by_osm_string[std::distance(osm_lane_strings, position)]; if (translated_mask == TurnLaneType::empty) { // if we have unsupported tags, don't handle them util::SimpleLogger().Write(logDEBUG) << "Unsupported lane tag found: \"" << *token_itr << "\""; return {}; } BOOST_ASSERT((lane_mask & translated_mask) == 0); // make sure the mask is valid lane_mask |= translated_mask; } // add the lane to the description lane_description.push_back(lane_mask); } return lane_description; }; // convert the lane description into an ID and, if necessary, remembr the description in the // description_map const auto requestId = [&](std::string lane_string) { if (lane_string.empty()) return INVALID_LANE_DESCRIPTIONID; TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string)); const auto lane_description_itr = lane_description_map.find(lane_description); if (lane_description_itr == lane_description_map.end()) { const LaneDescriptionID new_id = boost::numeric_cast<LaneDescriptionID>(lane_description_map.size()); lane_description_map[lane_description] = new_id; // since we are getting a new ID, we can augment the current offsets // and store the turn lane masks, sadly stxxl does not support insert for (const auto mask : lane_description) external_memory.turn_lane_masks.push_back(mask); external_memory.turn_lane_offsets.push_back(external_memory.turn_lane_offsets.back() + lane_description.size()); return new_id; } else { return lane_description_itr->second; } }; // Deduplicates street names and street destination names based on the street_map map. // In case we do not already store the name, inserts (name, id) tuple and return id. // Otherwise fetches the id based on the name and returns it without insertion. const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward); const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward); const constexpr auto MAX_STRING_LENGTH = 255u; // Get the unique identifier for the street name // Get the unique identifier for the street name and destination const auto name_iterator = string_map.find(MapKey(parsed_way.name, parsed_way.destinations)); unsigned name_id = EMPTY_NAMEID; if (string_map.end() == name_iterator) { const auto name_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.name.size()); const auto destinations_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.destinations.size()); const auto pronunciation_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.pronunciation.size()); // name_offsets already has an offset of a new name, take the offset index as the name id name_id = external_memory.name_offsets.size() - 1; external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length + destinations_length + pronunciation_length); std::copy(parsed_way.name.c_str(), parsed_way.name.c_str() + name_length, std::back_inserter(external_memory.name_char_data)); external_memory.name_offsets.push_back(external_memory.name_char_data.size()); std::copy(parsed_way.destinations.c_str(), parsed_way.destinations.c_str() + destinations_length, std::back_inserter(external_memory.name_char_data)); external_memory.name_offsets.push_back(external_memory.name_char_data.size()); std::copy(parsed_way.pronunciation.c_str(), parsed_way.pronunciation.c_str() + pronunciation_length, std::back_inserter(external_memory.name_char_data)); external_memory.name_offsets.push_back(external_memory.name_char_data.size()); auto k = MapKey{parsed_way.name, parsed_way.destinations}; auto v = MapVal{name_id}; string_map.emplace(std::move(k), std::move(v)); } else { name_id = name_iterator->second; } const bool split_edge = (parsed_way.forward_speed > 0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) && (parsed_way.backward_speed > 0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) && ((parsed_way.forward_speed != parsed_way.backward_speed) || (parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) || (turn_lane_id_forward != turn_lane_id_backward)); external_memory.used_node_id_list.reserve(external_memory.used_node_id_list.size() + input_way.nodes().size()); std::transform(input_way.nodes().begin(), input_way.nodes().end(), std::back_inserter(external_memory.used_node_id_list), [](const osmium::NodeRef &ref) { return OSMNodeID{static_cast<std::uint64_t>(ref.ref())}; }); const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode; // traverse way in reverse in this case if (is_opposite_way) { BOOST_ASSERT(split_edge == false); BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE); util::for_each_pair( input_way.nodes().crbegin(), input_way.nodes().crend(), [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { external_memory.all_edges_list.push_back( InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, name_id, backward_weight_data, true, false, parsed_way.roundabout, parsed_way.is_access_restricted, parsed_way.is_startpoint, parsed_way.backward_travel_mode, false, turn_lane_id_backward, road_classification)); }); external_memory.way_start_end_id_list.push_back( {OSMWayID{static_cast<std::uint32_t>(input_way.id())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}}); } else { const bool forward_only = split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode; util::for_each_pair( input_way.nodes().cbegin(), input_way.nodes().cend(), [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { external_memory.all_edges_list.push_back( InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, name_id, forward_weight_data, true, !forward_only, parsed_way.roundabout, parsed_way.is_access_restricted, parsed_way.is_startpoint, parsed_way.forward_travel_mode, split_edge, turn_lane_id_forward, road_classification)); }); if (split_edge) { BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE); util::for_each_pair( input_way.nodes().cbegin(), input_way.nodes().cend(), [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { external_memory.all_edges_list.push_back( InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, name_id, backward_weight_data, false, true, parsed_way.roundabout, parsed_way.is_access_restricted, parsed_way.is_startpoint, parsed_way.backward_travel_mode, true, turn_lane_id_backward, road_classification)); }); } external_memory.way_start_end_id_list.push_back( {OSMWayID{static_cast<std::uint32_t>(input_way.id())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())}, OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}}); } }
void middle_ram_t::ways_set(osmium::Way const &way) { ways.set(way.id(), new ramWay(way, out_options->extra_attributes)); }