в OSM файле мало данных?

Всем привет.

Не так давно мне нужно было вытащить адреса и координаты домов из osm-файла. Я перенес данные файла в MySQL, потом написал скрипт, который вытаскивает нужные данные из базы.
Таким образом мне удалось получить данные по Минску. Тестил на 10 - 15 адресах, привязка сделана правильно (адрес - координаты).
При попытке сделать тоже самое для других областных центров (Гомель, Витебск, …) - данных почти нет. В конечном счете я получаю десяток адресов.

Там (в osm-файле) нет данных? Или они храняться как-то по-другому (в разных тегах и т.п.), чем данные по Минску?

Hi,
please consult the Russia forum:
http://forum.openstreetmap.org/viewforum.php?id=21
or write in English. :wink:

Edit: Post moved to Russia forum.

да, теги адресации могут быть на разных объектах. http://wiki.openstreetmap.org/wiki/RU:Key:addr

zsi, давайте подробности. Как переносили в мускуль, как потом доставали адреса.

Подробности? Ну ладно )

Так как существующими средствами перенести данные у меня не получилось (об этом я тоже спрашивал http://forum.openstreetmap.org/viewtopic.php?id=18704), то решил написать небольшую прогу на Java, которая просто пробегается по всем тегам, и заносит инфу в базу сохраняя привязку элементов.
Предварительно вырезав нужную мне область с помощью ‘osmosis’.

osmosis --read-xml file="BY.osm" --bounding-box top=53.997 left=27.375 bottom=53.794 right=27.879 --write-xml file="minsk.osm"

Проанализировав osm-файл и определив в каких тегах хранится нужная мне информация, составил sql-запросы для ее получения.
Точнее написал PHP-скрипт, который вытаскивает инфу из базы и сохраняет в нужном мне формате.

Все это делалось пару месяцев назад, поэтому подробности (из каких тегов бралось) уже не помню.
Если кому интересно может покопаться в исходниках.

Основной скрипт:


#!/usr/bin/php -q

<?php
	ini_set('memory_limit', '2000M');
	set_time_limit(0);
	
	try{
		define('EXE', 1);
		require_once "lib/config.php";
		require_once "functions/db_func.php";
		require_once "functions/asist_func.php";

		echo 'START: '.date('Y-m-d H:i:s')."\n\n";
		
		$sity_id = getSityRegionID('Минск');
	
		if($sity_id <= 0){
			echo 'Wrong sity_id';exit;
		}
		
		echo date('H:i:s').' get addresses... ';
		$addresses = getListAddressesID($sity_id);
		echo 'complete;'."\n";
		
		$fp = fopen('map_address.xml', 'w');
		write_data($fp, "<addresses>\n");
		
		$num_addr = count($addresses);
		for($i=0; $i < $num_addr; ++$i){
			if(isElementAddress($addresses[$i])){
				echo date('H:i:s').' get street name... ';
				$street_name = getStreetName($addresses[$i]);
				echo $street_name."\n";
				
				if(!empty($street_name)){
					write_data($fp, "\t<street name='".$street_name."'>\n");
					
					echo date('H:i:s').' get houses... ';
					$houses = getListHousesID($addresses[$i]);
					echo 'complete;'."\n";
					
					$num_houses = count($houses);
					for($j=0; $j < $num_houses; ++$j){
						echo date('H:i:s').' get hous name... ';
						$house_name = getHouseName($houses[$j]);
						echo $house_name."\n";
						
						if(!empty($house_name)){
							echo date('H:i:s').' get points... ';
							$house_points = getHousePointsID($houses[$j]);
							echo 'complete;'."\n";
							
							$lon_list = array();
							$lat_list = array();
							
							$num_points = count($house_points);
							for($k=0; $k < $num_points; ++$k){
								$point = getPointInfo($house_points[$k]);
								
								if(!empty($point['lon']) && !empty($point['lat'])){
									echo "\t".$k.' lon: '.$point['lon'].'; lat: '.$point['lat'].";\n";
									
									$lon_list[] = (float) $point['lon'];
									$lat_list[] = (float) $point['lat'];
								}
							}
							
							$max_lon = max($lon_list);
							$min_lon = min($lon_list);
							
							$max_lat = max($lat_list);
							$min_lat = min($lat_list);
							
							$lon_center = ($min_lon + $max_lon) / 2;
							$lat_center = ($min_lat + $max_lat) / 2;
							
							echo "\t".'center: lon: '.$lon_center.'; lat: '.$lat_center."\n";
							
							write_data($fp, "\t\t<house name='".$house_name."' lon='".$lon_center."' lat='".$lat_center."' />\n");
						}
					}
					
					write_data($fp, "\t</street>\n");
				}
			}
		}
		
		write_data($fp, "</addresses>");
	}
	catch (Exception $e){
		print_r($e);
	}
	
	fclose($fp);
	
	echo "\n\n".'END: '.date('Y-m-d H:i:s')."\n";
?>

db_func.php:


<?php
         function getSityRegionID($sity_name){
		$result = mysql_query("SELECT `parent_id` FROM `tag` WHERE (`parent_name`='relation' AND `k`='address:a3' AND `v`='".$sity_name."')") OR DIE(mysql_error());
		
		$sity_id = 0;
		$num_rows = mysql_num_rows($result);
		if($num_rows > 0){
			$row = mysql_fetch_array($result);
			$sity_id = $row['parent_id'];
		}

		return $sity_id;
	}

	function getListAddressesID($sity_id){
		$addresses = array();
		
		$result = mysql_query("SELECT `parent_id` FROM member WHERE (`type`='relation' AND `ref`='".$sity_id."' AND `role`='is_in')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		for($i = 0; $i < $num_rows; $i++){
			$row = mysql_fetch_array($result);
			$addresses[] = $row['parent_id'];
		}

		return $addresses;
	}
	
	function isElementAddress($address_id){
		$result = mysql_query("SELECT count(*) FROM tag WHERE (`parent_id`= '".$address_id."' AND `k`='type' AND `v`='address')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		return ($num_rows > 0);
	}
	
	function getStreetName($address_id){
		$result = mysql_query("SELECT `v` FROM tag WHERE (`parent_id`= '".$address_id."' AND `k`='address:a6')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		$street_name = '';
		if($num_rows > 0){
			$row = mysql_fetch_array($result);
			$street_name = $row['v'];
		}
		
		return $street_name;
	}
	
	function getListHousesID($address_id){
		$houses = array();
		
		$result = mysql_query("SELECT `ref` FROM member WHERE (`parent_id`= '".$address_id."' AND `type`='way' AND `role`='house')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		for($i = 0; $i < $num_rows; $i++){
			$row = mysql_fetch_array($result);
			$houses[] = $row['ref'];
		}

		return $houses;
	}
	
	function getHouseName($house_id){
		$result = mysql_query("SELECT `v` FROM tag WHERE (`parent_id`= '".$house_id."' AND `k`='addr:housenumber')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		$house_name = '';
		if($num_rows > 0){
			$row = mysql_fetch_array($result);
			$house_name = $row['v'];
		}
		
		return $house_name;
	}
	
	function getHousePointsID($house_id){
		$points = array();
		
		$result = mysql_query("SELECT `ref` FROM nd WHERE (`parent_id`= '".$house_id."' AND `parent_name`='way')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		for($i = 0; $i < $num_rows; $i++){
			$row = mysql_fetch_array($result);
			$points[] = $row['ref'];
		}

		return $points;
	}
	
	function getPointInfo($point_id){
		$result = mysql_query("SELECT `lon`, `lat` FROM node WHERE (`id`= '".$point_id."')") OR DIE(mysql_error());
		$num_rows = mysql_num_rows($result);
		
		$point = array();
		
		if($num_rows > 0){
			$row = mysql_fetch_array($result);
			$point['lon'] = $row['lon'];
			$point['lat'] = $row['lat'];
		}

		return $point;
	}
?>

asist_func.php:


<?php
        function write_data($fp, $data_string){
		if(fwrite($fp, $data_string) == FALSE) {
			echo '--- error write data ---'."\n";
			exit;
		}
	}
?>

Вроде все.

Ага, ну если я понял, то ты (можно на ты ладно) выдираешь адреса из отношений. Далеко не все адреса хранятся таким образом. Собственно основной путь - это addr:street + addr:housenumber на домик (тоесть на замкнутый вей) и остальная информация на полигоне города. Соответсвенно адреса выдергиваются джоином домиков и охватывающего полигона.

Если это не в целях обучения/тренировки проще вытащить с гислаба из постгрехи (1 несложный запрос).

Все это делается в целях получить нужные данные с минимальными трудозатратами и забыть )
С постгрехи у меня возникли проблемы когда я пытался перенести туда данные с помощью osmsis. В общем, в этом случае нужно упорно разбираться с постгрехи, а это мне совсем не хочется )

Если не сложно, можно небольшой пример того, как данные точно будут хранится? А то никакой связи между нужными мне элементами (кроме той которую я описал в предыдущем посте) я найти не могу.

Не секрет, зачем именно нужны выгрузки адресов?
И в каком виде нужны координаты домов, достаточно ли широты-долготы на дом?

Вот тут было на тему:
http://www.openstreetmap.org/user/Zkir/diary/17862

:slight_smile:

Если нужно один раз с минимумом гемороя - разжалоби Zkira у него доброе сердце и можно попытаться отъехать от выплаты 100 евров.
Ну или ставь клиента от постгрехи и:


psql --host gis-lab.info --user guest --dbname osm_shp -c "select ST_X(b.geom), ST_Y(b.geom), b.\"A_STRT\", b.\"A_HSNMBR\", setle.\"NAME\" from layer.\"BY building-point\" b join layer.\"BY settlement-polygon\" setle on ST_Contains(setle.geom, b.geom) where b.\"A_HSNMBR\" is not null;"

Пароль guest, почитав psql --help можно добиться выгрузки в csv

И да, если данных всеравно маловато, стоит посмотреть, внесены ли эти данные в осм :slight_smile:

спасибо

Не ну хоть отпишись что получилось/не получилось