예제 #1
0
                void way(const osmium::Way& way) {
                    if (m_write_change_ops) {
                        open_close_op_tag(way.visible() ? (way.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete);
                    }

                    write_prefix();
                    m_out += "<way";
                    write_meta(way);

                    if (way.tags().empty() && way.nodes().empty()) {
                        m_out += "/>\n";
                        return;
                    }

                    m_out += ">\n";

                    for (const auto& node_ref : way.nodes()) {
                        write_prefix();
                        oprintf(m_out, "  <nd ref=\"%" PRId64 "\"/>\n", node_ref.ref());
                    }

                    write_tags(way.tags());

                    write_prefix();
                    m_out += "</way>\n";
                }
예제 #2
0
                void way(const osmium::Way& way) {
                    *m_out += 'w';
                    write_meta(way);

                    *m_out += " N";

                    if (!way.nodes().empty()) {
                        auto it = way.nodes().begin();
                        if (m_options.locations_on_ways) {
                            write_field_ref(*it);
                            for (++it; it != way.nodes().end(); ++it) {
                                *m_out += ',';
                                write_field_ref(*it);
                            }
                        } else {
                            write_field_int('n', it->ref());
                            for (++it; it != way.nodes().end(); ++it) {
                                *m_out += ',';
                                write_field_int('n', it->ref());
                            }
                        }
                    }

                    *m_out += '\n';
                }
예제 #3
0
 /**
  * Extract segments from given way and add them to the list.
  *
  * Segments connecting two nodes with the same location (ie
  * same node or different nodes with same location) are
  * removed after reporting the duplicate node.
  */
 uint32_t extract_segments_from_way(osmium::area::ProblemReporter* problem_reporter, const osmium::Way& way) {
     if (way.nodes().empty()) {
         return 0;
     }
     m_segments.reserve(way.nodes().size() - 1);
     return extract_segments_from_way_impl(problem_reporter, way, role_type::outer);
 }
    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);
    }
예제 #5
0
    void way(const osmium::Way& way) {
        // detect a new way
        if (current_way_id != 0 && current_way_id != way.positive_id()) {
            write_way_extra_nodes();
            current_way_nodes.clear();
        }
        current_way_id = way.positive_id();

        if (debug) {
            std::cerr << "softcut way " << way.positive_id() << " v" << way.version() << "\n";
        }

        for (const auto& node_ref : way.nodes()) {
            current_way_nodes.insert(node_ref.positive_ref());
        }

        for (const auto& extract : info->extracts) {
            for (const auto& node_ref : way.nodes()) {
                if (extract->node_tracker.get(node_ref.positive_ref())) {
                    if (debug) {
                        std::cerr << "way has a node (" << node_ref.positive_ref() << ") inside extract, recording in way_tracker\n";
                    }
                    extract->way_tracker.set(way.positive_id());
                    break;
                }
            }
        }
    }
예제 #6
0
 /***
  * Insert error node into nodes table: way contains of one
  * coordinate.
  */
 void insert_way_error(const osmium::Way &way) {
     ErrorSum *sum = new ErrorSum();
     sum->set_way_error();
     ds.insert_node_feature(way.nodes().begin()->location(),
                            way.nodes().begin()->ref(), sum);
     delete sum;
 }
 void eway(extract_data& e, const osmium::Way& way) {
     for (const auto& nr : way.nodes()) {
         if (e.node_ids.get(nr.positive_ref())) {
             e.way_ids.set(way.positive_id());
             for (const auto& nr : way.nodes()) {
                 e.extra_node_ids.set(nr.ref());
             }
             return;
         }
     }
 }
예제 #8
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;
            }
예제 #9
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;
                }
예제 #10
0
 /***
  * Iterate through all nodes of waterways in pass 3 if way is coastline
  * or riverbank. Otherwise iterate just through the nodes between
  * firstnode and lastnode.
  */
 void way(const osmium::Way& way) {
     if (is_valid(way)) {
         if (check_all_nodes(way)) {
             for (auto node : way.nodes()) {
                 check_node(node);
             }
         } else {
             if (way.nodes().size() > 2) {
                 for (auto node = way.nodes().begin() + 1;
                         node != way.nodes().end() - 1; ++node) {
                     check_node(*node);
                 }
             }
         }
     }
 }
예제 #11
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);
            }
        }

    }
}
예제 #12
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;
     }
 }
예제 #13
0
 /**
  * Extract segments from given way and add them to the list.
  *
  * Segments connecting two nodes with the same location (ie same
  * node or different node with same location) are removed.
  *
  * XXX should two nodes with same location be reported?
  */
 void extract_segments_from_way(const osmium::Way& way, const char* role) {
     osmium::NodeRef last_nr;
     for (const osmium::NodeRef& nr : way.nodes()) {
         if (last_nr.location() && last_nr.location() != nr.location()) {
             m_segments.emplace_back(last_nr, nr, role, &way);
         }
         last_nr = nr;
     }
 }
 /**
  * This is called when a way is not in any multipolygon
  * relation.
  */
 void way_not_in_any_relation(const osmium::Way& way) {
     // you need at least 4 nodes to make up a polygon
     if (way.nodes().size() <= 3) {
         return;
     }
     try {
         if (!way.nodes().front().location() || !way.nodes().back().location()) {
             throw osmium::invalid_location{"invalid location"};
         }
         if (way.ends_have_same_location()) {
             // way is closed and has enough nodes, build simple multipolygon
             TAssembler assembler{m_assembler_config};
             assembler(way, this->buffer());
             m_stats += assembler.stats();
         }
     } catch (const osmium::invalid_location&) {
         // XXX ignore
     }
 }
예제 #15
0
 /**
  * This is called when a way is not in any multipolygon
  * relation.
  *
  * Overwritten from the base class.
  */
 void way_not_in_any_relation(const osmium::Way& way) {
     // you need at least 4 nodes to make up a polygon
     if (way.nodes().size() <= 3) {
         return;
     }
     try {
         if (!way.nodes().front().location() || !way.nodes().back().location()) {
             throw osmium::invalid_location("invalid location");
         }
         if (way.ends_have_same_location()) {
             // way is closed and has enough nodes, build simple multipolygon
             TAssembler assembler(m_assembler_config);
             assembler(way, m_output_buffer);
             possibly_flush_output_buffer();
         }
     } catch (osmium::invalid_location&) {
         // XXX ignore
     }
 }
 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;
     }
 }
예제 #17
0
    // The way handler is called for each node in the input data.
    void way(const osmium::Way& way) {
        {
            osmium::builder::WayBuilder builder{m_buffer};
            copy_attributes(builder, way);
            copy_tags(builder, way.tags());

            // Copy the node list over to the new way.
            builder.add_item(way.nodes());
        }
        m_buffer.commit();
    }
예제 #18
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);
    }
}
 /**
  * This is called when a way is not in any multipolygon
  * relation.
  *
  * Overwritten from the base class.
  */
 void way_not_in_any_relation(const osmium::Way& way) {
     if (way.nodes().size() > 3 && way.ends_have_same_location()) {
         // way is closed and has enough nodes, build simple multipolygon
         try {
             TAssembler assembler(m_assembler_config);
             assembler(way, m_output_buffer);
             possibly_flush_output_buffer();
         } catch (osmium::invalid_location&) {
             // XXX ignore
         }
     }
 }
예제 #20
0
 void way(const osmium::Way& way) {
     for (const auto& node_ref : way.nodes()) {
         try {
             add_location(m_old_index.get(node_ref.ref()));
         } catch (...) {
         }
         try {
             add_location(m_tmp_index.get(node_ref.ref()));
         } catch (...) {
         }
     }
 }
예제 #21
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();
     }
 // - 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());
                 }
             }
         }
     }
 }
예제 #23
0
                void way(const osmium::Way& way) {
                    *m_out += 'w';
                    write_meta(way);

                    *m_out += " N";
                    bool first = true;
                    for (const auto& node_ref : way.nodes()) {
                        if (first) {
                            first = false;
                        } else {
                            *m_out += ',';
                        }
                        output_formatted("n%" PRId64, node_ref.ref());
                    }
                    *m_out += '\n';
                }
예제 #24
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";
        }
    }
예제 #25
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;
}
 /**
  * Retrieve locations of all nodes in the way from storage and add
  * them to the way object.
  */
 void way(osmium::Way& way) {
     if (m_must_sort) {
         m_storage_pos.sort();
         m_storage_neg.sort();
         m_must_sort = false;
         m_last_id = std::numeric_limits<osmium::unsigned_object_id_type>::max();
     }
     bool error = false;
     for (auto& node_ref : way.nodes()) {
         node_ref.set_location(get_node_location(node_ref.ref()));
         if (!node_ref.location()) {
             error = true;
         }
     }
     if (!m_ignore_errors && error) {
         throw osmium::not_found{"location for one or more nodes not found in node location index"};
     }
 }
void CreateGraph::way(const osmium::Way& way)
{
  const char* highway = way.get_value_by_key("highway");
  if (!highway || !strcmp(highway, "footway"))
  {
    return;
  }

  vertex_type u = -1;
  for (const auto& node_ref : way.nodes())
  {
    node_id_map_type::iterator pos;
    bool inserted;
    boost::tie(pos, inserted) = node_id_map.emplace(node_ref.positive_ref(), vertex_type());

    if (inserted)
    {
      double x = osmium::geom::detail::lon_to_x(node_ref.lon());
      double y = osmium::geom::detail::lat_to_y(node_ref.lat());
      Location loc(x, y);

      pos->second = boost::add_vertex(vertex_property(loc), graph);
    }

    const vertex_type v = pos->second;

    if (u+1)
    {
      const char* street_name = way.get_value_by_key("name", "");

      const Location& a = boost::get(boost::vertex_name, graph, u);
      const Location& b = boost::get(boost::vertex_name, graph, v);
      const double length = dist(a, b);

      edge_property prop;
      boost::get_property_value(prop, boost::edge_name) = street_name;
      boost::get_property_value(prop, boost::edge_weight) = length;

      boost::add_edge(u, v, prop, graph);
    }

    u = v;
  }
}
예제 #28
0
	bool is_way_with_nonzero_length(const osmium::Way& way) {
		if (way.nodes().size() < 2) {
			return false;
		}
		for (unsigned int i=1; i<way.nodes().size(); i++) {
			if (way.nodes()[0].location().lat() != way.nodes()[i].location().lat()) {
				return true;
			}
			if (way.nodes()[0].location().lon() != way.nodes()[i].location().lon()) {
				return true;
			}
		}
		return false;
	}
 /**
  * Retrieve locations of all nodes in the way from storage and add
  * them to the way object.
  */
 void way(osmium::Way& way) {
     if (m_must_sort) {
         m_storage_pos.sort();
         m_storage_neg.sort();
         m_must_sort = false;
     }
     bool error = false;
     for (auto& node_ref : way.nodes()) {
         try {
             node_ref.set_location(get_node_location(node_ref.ref()));
             if (!node_ref.location()) {
                 error = true;
             }
         } catch (osmium::not_found&) {
             error = true;
         }
     }
     if (error && !m_ignore_errors) {
         throw osmium::not_found("location for one or more nodes not found in node location index");
     }
 }
예제 #30
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";
                }
            }
        }
    }