void operator()(const hypergraph_type& source, hypergraph_type& target) { // first, copy... target = source; if (! source.is_valid()) return; phrase_type binarized(2); hypergraph_type::edge_type::node_set_type tails(2); // we will traverse source-side in order to avoid confusion with newly created nodes... removed_type removed(source.edges.size(), false); position_set_type positions; node_chart_type node_chart; label_chart_type label_chart; label_map.clear(); node_map.clear(); hypergraph_type::node_set_type::const_iterator niter_end = source.nodes.end(); for (hypergraph_type::node_set_type::const_iterator niter = source.nodes.begin(); niter != niter_end; ++ niter) { const hypergraph_type::node_type& node_source = *niter; hypergraph_type::node_type::edge_set_type::const_iterator eiter_end = node_source.edges.end(); for (hypergraph_type::node_type::edge_set_type::const_iterator eiter = node_source.edges.begin(); eiter != eiter_end; ++ eiter) { const hypergraph_type::edge_type& edge_source = source.edges[*eiter]; if (edge_source.tails.size() <= 2) continue; removed[edge_source.id] = true; // we will create nodes in a chart structure, and exhaustively enumerate edges symbol_set_type rhs_sorted(edge_source.rule->rhs); tail_set_type tails_sorted(edge_source.tails); // first, compute non-terminal spans... positions.clear(); int pos = 0; for (size_t i = 0; i != rhs_sorted.size(); ++ i) if (rhs_sorted[i].is_non_terminal()) { const int non_terminal_index = rhs_sorted[i].non_terminal_index(); tails_sorted[pos] = edge_source.tails[utils::bithack::branch(non_terminal_index == 0, pos, non_terminal_index - 1)]; rhs_sorted[i] = rhs_sorted[i].non_terminal(); positions.push_back(i); ++ pos; } if (positions.size() != edge_source.tails.size()) throw std::runtime_error("invalid edge: # of non-terminals and tails size do not match"); // seond, enumerate chart to compute node and edges... node_chart.clear(); node_chart.resize(positions.size() + 1, hypergraph_type::invalid); label_chart.clear(); label_chart.resize(positions.size() + 1); for (size_t i = 0; i != positions.size(); ++ i) { node_chart(i, i + 1) = tails_sorted[i]; label_chart(i, i + 1) = rhs_sorted[positions[i]]; } for (size_t length = 2; length < positions.size(); ++ length) for (size_t first = 0; first + length <= positions.size(); ++ first) { const size_t last = first + length; const symbol_set_type subrhs(rhs_sorted.begin() + positions[first], rhs_sorted.begin() + positions[last - 1] + 1); const tail_set_type subtails(tails_sorted.begin() + first, tails_sorted.begin() + last); std::pair<label_map_type::iterator, bool> result_label = label_map.insert(std::make_pair(subtails, symbol_type())); if (result_label.second) { const symbol_type::piece_type left = label_chart(first, last - 1).non_terminal_strip(); const symbol_type::piece_type right = label_chart(last - 1, last).non_terminal_strip(); if (length > 2) result_label.first->second = '[' + std::string(left.begin(), left.end() - 1) + '+' + right + "^]"; else result_label.first->second = '[' + std::string(left) + '+' + right + "^]"; } std::pair<node_map_type::iterator, bool> result_node = node_map.insert(std::make_pair(tail_symbol_pair_type(subtails, subrhs), 0)); if (result_node.second) result_node.first->second = target.add_node().id; const symbol_type lhs = result_label.first->second; const hypergraph_type::id_type head = result_node.first->second; node_chart(first, last) = head; label_chart(first, last) = lhs; // if newly created, then, create edges if (result_node.second) for (size_t middle = first + 1; middle != last; ++ middle) { // [first, middle) and [middle, last) tails.front() = node_chart(first, middle); tails.back() = node_chart(middle, last); const size_t middle_first = positions[middle - 1] + 1; const size_t middle_last = positions[middle]; binarized.clear(); binarized.push_back(label_chart(first, middle)); binarized.insert(binarized.end(), rhs_sorted.begin() + middle_first, rhs_sorted.begin() + middle_last); binarized.push_back(label_chart(middle, last)); hypergraph_type::edge_type& edge_new = target.add_edge(tails.begin(), tails.end()); edge_new.rule = rule_type::create(rule_type(lhs, binarized.begin(), binarized.end())); target.connect_edge(edge_new.id, head); } } // root... { const size_t first = 0; const size_t last = positions.size(); const hypergraph_type::id_type head = node_source.id; const symbol_type& lhs = edge_source.rule->lhs; node_chart(first, last) = head; label_chart(first, last) = lhs; for (size_t middle = first + 1; middle != last; ++ middle) { // [first, middle) and [middle, last) tails.front() = node_chart(first, middle); tails.back() = node_chart(middle, last); binarized.clear(); const size_t prefix_first = 0; const size_t prefix_last = positions[first]; binarized.insert(binarized.end(), rhs_sorted.begin() + prefix_first, rhs_sorted.begin() + prefix_last); binarized.push_back(label_chart(first, middle)); const size_t middle_first = positions[middle - 1] + 1; const size_t middle_last = positions[middle]; binarized.insert(binarized.end(), rhs_sorted.begin() + middle_first, rhs_sorted.begin() + middle_last); binarized.push_back(label_chart(middle, last)); const size_t suffix_first = positions[last - 1] + 1; const size_t suffix_last = rhs_sorted.size(); binarized.insert(binarized.end(), rhs_sorted.begin() + suffix_first, rhs_sorted.begin() + suffix_last); hypergraph_type::edge_type& edge_new = target.add_edge(tails.begin(), tails.end()); edge_new.rule = rule_type::create(rule_type(lhs, binarized.begin(), binarized.end())); edge_new.features = edge_source.features; edge_new.attributes = edge_source.attributes; target.connect_edge(edge_new.id, head); } } } } // further resize... removed.resize(target.edges.size(), false); hypergraph_type graph_removed; topologically_sort(target, graph_removed, filter(removed)); target.swap(graph_removed); }
void feed_way(const osmium::Way& way) { try { const char* interpolation = way.tags().get_value_by_key("addr:interpolation"); if (interpolation) { std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way); OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn()); const osmium::object_id_type first_node_id = m_geometry_helper.get_first_node_id(way); const osmium::object_id_type last_node_id = m_geometry_helper.get_last_node_id(way); feature->SetGeometry(ogr_linestring.get()); feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok? feature->SetField("typename", interpolation); feature->SetField("firstid", static_cast<double>(first_node_id)); //TODO: node.id() is of type int64_t. is cast do double ok? feature->SetField("lastid", static_cast<double>(last_node_id)); //TODO: node.id() is of type int64_t. is cast do double ok? feature->SetField("lastchange", way.timestamp().to_iso().c_str()); AltTagList first_taglist = m_addr_interpolation_node_map->get(first_node_id); AltTagList last_taglist = m_addr_interpolation_node_map->get(last_node_id); std::string first_node_housenumber = first_taglist.get_value_by_key(std::string("addr:housenumber")); std::string last_node_housenumber = last_taglist.get_value_by_key(std::string("addr:housenumber")); unsigned int first; unsigned int last; if (first_node_housenumber != "") { feature->SetField("firstno", first_node_housenumber.c_str()); first = atoi(first_node_housenumber.c_str()); } else { first = 0; } if (last_node_housenumber != "") { feature->SetField("lastno", last_node_housenumber.c_str()); last = atoi(last_node_housenumber.c_str()); } else { last = 0; } if (!(!strcmp(interpolation,"all") || !strcmp(interpolation,"even") || !strcmp(interpolation,"odd"))) { // TODO: add support for 'alphabetic' feature->SetField("error", "unknown interpolation type"); } else if ( first == 0 || last == 0 || first_node_housenumber.length() != floor(log10(first))+1 || // make sure 123%& is not recognized as 123 last_node_housenumber.length() != floor(log10(last) )+1 // ) { feature->SetField("error", "endpoint hast wrong format"); } else if (abs(first-last) > 1000) { feature->SetField("error", "range too large"); } else if (((!strcmp(interpolation,"even") || !strcmp(interpolation,"odd")) && abs(first-last)==2) || (!strcmp(interpolation,"all") && abs(first-last)==1) ) { feature->SetField("error", "needless interpolation"); } else if (!strcmp(interpolation,"even") && ( first%2==1 || last%2==1 )) { feature->SetField("error", "interpolation even but number odd"); } else if (!strcmp(interpolation,"odd") && ( first%2==0 || last%2==0 )) { feature->SetField("error", "interpolation odd but number even"); } else if ( (first_taglist.get_value_by_key(std::string("addr:street")) != last_taglist.get_value_by_key(std::string("addr:street"))) || (first_taglist.get_value_by_key(std::string("addr:postcode")) != last_taglist.get_value_by_key(std::string("addr:postcode"))) || (first_taglist.get_value_by_key(std::string("addr:city")) != last_taglist.get_value_by_key(std::string("addr:city"))) || (first_taglist.get_value_by_key(std::string("addr:country")) != last_taglist.get_value_by_key(std::string("addr:country"))) || (first_taglist.get_value_by_key(std::string("addr:full")) != last_taglist.get_value_by_key(std::string("addr:full"))) || (first_taglist.get_value_by_key(std::string("addr:place")) != last_taglist.get_value_by_key(std::string("addr:place"))) ) { feature->SetField("error", "different tags on endpoints"); } else if ( // no interpolation error (!strcmp(interpolation, "all")) || (!strcmp(interpolation, "odd")) || (!strcmp(interpolation, "even")) ) { double length = ogr_linestring.get()->get_Length(); int increment; if (strcmp(interpolation, "all")) { increment = 2; } else { increment = 1; } double fraction; unsigned int lower, upper; if (first < last) { fraction = 1/static_cast<double>(last-first); lower = first; upper = last; } else { fraction = 1/static_cast<double>(first-last); increment *= -1; lower = last; upper = first; } for (unsigned int nr=first+increment; nr<upper && nr>lower; nr+=increment) { std::unique_ptr<OGRPoint> point (new OGRPoint); if (increment > 0) { ogr_linestring.get()->Value((nr-lower)*fraction*length, point.get()); } else { ogr_linestring.get()->Value((1-((nr-lower)*fraction))*length, point.get()); } std::string road_id(""); m_clpp.process_interpolated_node( *(point.get()), road_id, first_taglist.get_value_by_key(std::string("addr:street")) ); m_nwa_writer.process_interpolated_node( *(point.get()), nr, first_taglist.get_value_by_key(std::string("addr:street")), first_taglist.get_value_by_key(std::string("addr:postcode")), first_taglist.get_value_by_key(std::string("addr:city")), first_taglist.get_value_by_key(std::string("addr:country")), first_taglist.get_value_by_key(std::string("addr:full")), first_taglist.get_value_by_key(std::string("addr:place")), road_id ); } } create_feature(feature); } } catch (osmium::geom::geometry_error& e) { catch_geometry_error(e, way); } }
void feed_way(const osmium::Way& way) { try { const char* interpolation = way.tags().get_value_by_key("addr:interpolation"); if (interpolation) { std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way); OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn()); const osmium::object_id_type first_node_id = m_geometry_helper.get_first_node_id(way); const osmium::object_id_type last_node_id = m_geometry_helper.get_last_node_id(way); feature->SetGeometry(ogr_linestring.get()); feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok? feature->SetField("typename", interpolation); feature->SetField("firstid", static_cast<double>(first_node_id)); //TODO: node.id() is of type int64_t. is cast do double ok? feature->SetField("lastid", static_cast<double>(last_node_id)); //TODO: node.id() is of type int64_t. is cast do double ok? feature->SetField("lastchange", way.timestamp().to_iso().c_str()); AltTagList first_taglist = m_addr_interpolation_node_map->get(first_node_id); AltTagList last_taglist = m_addr_interpolation_node_map->get(last_node_id); // the raw expression given in the first addr:housenumber= entry std::string first_raw = first_taglist.get_value_by_key("addr:housenumber"); // the raw expression given in the last addr:housenumber= entry std::string last_raw = last_taglist.get_value_by_key("addr:housenumber"); unsigned int first; unsigned int last; std::string first_numeric; // the numeric part of the first housenumber std::string last_numeric; // the numeric part of the last housenumber bool is_alphabetic_ip_correct = false; if (first_raw != "") { feature->SetField("firstno", first_raw.c_str()); first = atoi(first_raw.c_str()); } else { first = 0; } if (last_raw != "") { feature->SetField("lastno", last_raw.c_str()); last = atoi(last_raw.c_str()); } else { last = 0; } if (!strcmp(interpolation, "alphabetic") && // second last characters are numbers? !isalpha(first_raw[first_raw.length()-2]) && !isalpha(last_raw[last_raw.length()-2])){ // last characters are letters? if (isalpha(first_raw[first_raw.length()-1]) && isalpha(last_raw[last_raw.length()-1])) { first_numeric = std::string(first_raw.begin(), first_raw.end() - 1); last_numeric = std::string(last_raw.begin(), last_raw.end() - 1); if (first_numeric == last_numeric) { first = first_raw[first_raw.length() - 1]; last = last_raw[last_raw.length() - 1]; is_alphabetic_ip_correct = true; } else { is_alphabetic_ip_correct = false; feature->SetField("error", "numeric parts of housenumbers not identical"); } } else { is_alphabetic_ip_correct = false; feature->SetField("error", "no alphabetic part in addr:housenumber"); } } if (!( !strcmp(interpolation, "all") || !strcmp(interpolation, "even") || !strcmp(interpolation, "odd") || !strcmp(interpolation, "alphabetic"))) { feature->SetField("error", "unknown interpolation type"); } else if ( strcmp(interpolation, "alphabetic") && // don't overwrite more precise error messages set before (first == 0 || last == 0 || first_raw.length() != floor(log10(first))+1 || // make sure 123%& is not recognized as 123 last_raw.length() != floor(log10(last) )+1 // )) { feature->SetField("error", "endpoint has wrong format"); } else if (abs_diff(first,last) > 1000) { feature->SetField("error", "range too large"); } else if (((!strcmp(interpolation,"even") || !strcmp(interpolation,"odd")) && abs_diff(first,last)==2) || (!strcmp(interpolation,"all") && abs_diff(first,last)==1) ) { feature->SetField("error", "needless interpolation"); } else if (!strcmp(interpolation,"even") && ( first%2==1 || last%2==1 )) { feature->SetField("error", "interpolation even but number odd"); } else if (!strcmp(interpolation,"odd") && ( first%2==0 || last%2==0 )) { feature->SetField("error", "interpolation odd but number even"); } else if ( (first_taglist.get_value_by_key("addr:street") != last_taglist.get_value_by_key("addr:street")) || (first_taglist.get_value_by_key("addr:postcode") != last_taglist.get_value_by_key("addr:postcode")) || (first_taglist.get_value_by_key("addr:city") != last_taglist.get_value_by_key("addr:city")) || (first_taglist.get_value_by_key("addr:country") != last_taglist.get_value_by_key("addr:country")) || (first_taglist.get_value_by_key("addr:full") != last_taglist.get_value_by_key("addr:full")) || (first_taglist.get_value_by_key("addr:place") != last_taglist.get_value_by_key("addr:place")) ) { feature->SetField("error", "different tags on endpoints"); } else if (way.is_closed()) { feature->SetField("error", "interpolation is a closed way"); } else if ( // no interpolation error (!strcmp(interpolation, "all")) || (!strcmp(interpolation, "odd")) || (!strcmp(interpolation, "even")) || (is_alphabetic_ip_correct == true)) { double length = ogr_linestring.get()->get_Length(); int increment; if (strcmp(interpolation, "all") && strcmp(interpolation, "alphabetic")) { increment = 2; // even , odd } else { increment = 1; //all , alphabetic } double fraction; unsigned int lower, upper; if (first < last) { fraction = 1/static_cast<double>(last-first); lower = first; upper = last; } else { fraction = 1/static_cast<double>(first-last); increment *= -1; lower = last; upper = first; } for (unsigned int nr=first+increment; nr<upper && nr>lower; nr+=increment) { std::unique_ptr<OGRPoint> point (new OGRPoint); if (increment > 0) { ogr_linestring.get()->Value((nr-lower)*fraction*length, point.get()); } else { ogr_linestring.get()->Value((1-((nr-lower)*fraction))*length, point.get()); } std::string road_id(""); std::string nrstr; if(strcmp(interpolation, "alphabetic")) { nrstr = std::to_string(nr); } else { // is alphabetic // std::string strend = printf("%d", nr); nrstr = first_numeric + static_cast<char>(nr); } m_clpp.process_interpolated_node( // osmi_addresses_connection_line *(point.get()), road_id, first_taglist.get_value_by_key("addr:street") ); m_nwa_writer.process_interpolated_node( //osmi_addresses_nodes_with_addresses *(point.get()), nrstr, //nr, //std::to_string(nr), first_taglist.get_value_by_key("addr:street"), first_taglist.get_value_by_key("addr:postcode"), first_taglist.get_value_by_key("addr:city"), first_taglist.get_value_by_key("addr:country"), first_taglist.get_value_by_key("addr:full"), first_taglist.get_value_by_key("addr:place"), road_id ); } } create_feature(feature); } } catch (osmium::geometry_error& e) { catch_geometry_error(e, way); } }
/** @throws std::out_of_range */ ConfigNode const& node( String const& name ) const { return m_nodes.at(name); }