Exemple #1
0
    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);
		}
	}
Exemple #4
0
	/** @throws std::out_of_range */
	ConfigNode const&
	node(
		String const& name
	) const {
		return m_nodes.at(name);
	}