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);
            }
        }

    }
}
Beispiel #2
0
 /**
  * Add way to collection. A new CoastlineRing will be created for the way
  * or it will be joined to an existing CoastlineRing.
  */
 void add_way(const osmium::Way& way) {
     m_ways++;
     if (way.is_closed()) {
         m_rings_from_single_way++;
         m_list.push_back(std::make_shared<CoastlineRing>(way));
     } else {
         add_partial_ring(way);
     }
 }
	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);
		}
	}
	void feed_way(const osmium::Way& way) {
		try {
			const char* building = way.tags().get_value_by_key("building");

			if (building && way.is_closed()) {
				std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
				OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
				OGRPolygon polygon;
				polygon.addRing(static_cast<OGRLinearRing*>(ogr_linestring.get()));
				feature->SetGeometry(static_cast<OGRGeometry*>(&polygon));

				feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok?
				feature->SetField("lastchange", way.timestamp().to_iso().c_str());

				create_feature(feature);
			}

		} catch (osmium::geom::geometry_error& e) {
			catch_geometry_error(e, way);
		}
	}
	void feed_way(const osmium::Way& way) {
		try {
			const char* building = way.tags().get_value_by_key("building");
			if (building && way.is_closed()) {
				const char* street   = way.tags().get_value_by_key("addr:street");
				const char* houseno  = way.tags().get_value_by_key("addr:housenumber");
				
				if (street || houseno) {
					std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
					OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
					OGRPolygon polygon;
					polygon.addRing(static_cast<OGRLinearRing*>(ogr_linestring.get()));
					feature->SetGeometry(static_cast<OGRGeometry*>(&polygon));
					feature->SetField("way_id", static_cast<double>(way.id())); //TODO: node.id() is of type int64_t. is this ok?
					feature->SetField("lastchange", way.timestamp().to_iso().c_str());

					const char* postcode = way.tags().get_value_by_key("addr:postcode");
					const char* city     = way.tags().get_value_by_key("addr:city");
					const char* country  = way.tags().get_value_by_key("addr:country");
					const char* fulladdr = way.tags().get_value_by_key("addr:full");
					const char* place    = way.tags().get_value_by_key("addr:place");

					if (street)   { feature->SetField("street"  , street);   }
					if (houseno)  { feature->SetField("houseno" , houseno);  }
					if (postcode) { feature->SetField("postcode", postcode); }
					if (city)     { feature->SetField("city",     city);     }
					if (country)  { feature->SetField("country",  country);  }
					if (fulladdr) { feature->SetField("fulladdr", fulladdr); }
					if (place)    { feature->SetField("place",    place);    }

					create_feature(feature);

				}
			}
		}
		catch (osmium::geometry_error& e) {
			catch_geometry_error(e, way);
		}
	}
	void 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);
		}
	}