Esempio n. 1
0
    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;
    }
Esempio n. 2
0
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);
            }
        }

    }
}
Esempio n. 3
0
    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);
         }
     }
 }
Esempio n. 6
0
        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();
        }
Esempio n. 7
0
            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();
            }
Esempio n. 8
0
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());
                 }
             }
         }
     }
 }
Esempio n. 10
0
            /**
             * 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;
            }
Esempio n. 11
0
    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);
    }
Esempio n. 13
0
                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;
                }
Esempio n. 14
0
 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;
     }
 }
Esempio n. 15
0
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;
     }
 }
Esempio n. 18
0
     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;
     }
 }
Esempio n. 20
0
    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;
	}
Esempio n. 23
0
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);
		}
	}
Esempio n. 26
0
  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';
 }
Esempio n. 29
0
/**
 * 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())}});
    }
}
Esempio n. 30
0
void middle_ram_t::ways_set(osmium::Way const &way)
{
    ways.set(way.id(), new ramWay(way, out_options->extra_attributes));
}