Як правильно вказувати адресу ?

[offtop]
Щодо нетбука toshiba AC100 : я зробив “reset to factory defaults”. Не допомогло. Все одно час від часу нетбук зависав. Тоді я відформатував розділ з юpерськими даними (при перепрошиванні його не чіпали) та скопіював все те “добро” назад, стало краще. Тепер вже не висне vplayer через 10 хвилин після запуску, і поки що немає спорадичних зависонів без причин.
Проблему з клавіатурою майже подолано: поставив Multiplay IME keyboard (довелося власноруч переробити турецьку розкладку на українську), але перестали працювати комбінації Ctrl+C, Ctrl+V, Ctrl+A. Але можна й без них. [/offtop]

Угу, воно дивиться на теґ street у відношенні. Ясно, чому не працює.

Я би в лоб, не дивлячись сильно на код, написав би так:


        while ( my ($relation_id, $members) = each %$list ) {
           my $street_member = first { $_->{type} eq 'way' && $_->{role} eq 'street' } @$members;
           next if !$street_member;

           $street_name = name_from_list( 'name', $waytag->{$street_member} );
           next if !$street_name;

Спробуй.

Так, воно бере тег name з відношення. В нас name відношення співпадає з назвою вулиці українською мовою. А при створенні карти на інших мовах виникає помилка.

Завтра спробую. Тільки спочатку знайду довідник з синтаксиса Перл.
Бо без довідника я якось розумію лише Бєйсік та Паскаль. :smiley: А тут ситаксіс не дуже схожий на паскалевський. Скоріше на С++

Ні, по коду воно бере власне с теґа street, а не name. Тому більшість відношень і пропускаються.

Спробував. Воно матюкається на $street_name
Я подивився на оригінальний код, інтуітивно дописав my перед $street_name у рядку

my $street_name = name_from_list( 'name', $waytag->{$street_member} );

Запустилося. Зараз чекаю на результат.

Результат поки невтішний. Я вказав брати назви з name:ru, name

perl osm2mp_sev.pl --config=cfg\navitel-ru.cfg --full-karlsruhe --navitel --bpoly OSM_UA_KHR.poly --namelist label=name:ru,name --namelist place=name:ru,name --namelist street=name:ru,name --defaultcountry="Ukraine" --defaultregion="Kharkivska obl." --codepage=utf8 --output=UA-KHR-ru.mp UA-KHR.osm

Воно видало “0 houses with associated street”. Відкриваю Харків, дивлюся: там, де будинки не мають addr:street, замість назви вулиці прописано “Харьков”. А там, де addr:street задано, воно вписало назву вулиці "Єлізарова вулиця"з addr:street. Хоча в параметрах задано брати назву з name:ru.

dimonster, а откуда ты пытаешься брать имя улицы?

Там задано --namelist label=name:ru,name --namelist place=name:ru,name --namelist street=name:ru,name

Index: osm2mp.pl
===================================================================
--- osm2mp.pl   (revision 581)
+++ osm2mp.pl   (working copy)
@@ -413,7 +413,17 @@
         next if !$list;

         while ( my ($relation_id, $members) = each %$list ) {
-            my $street_name = name_from_list( 'street', $reltag->{$relation_id} );
+            my $street_name;
+            for my $member ( @$members ) {
+               next if !( $member->{role} eq 'street' );
+               next if !( $member->{type} eq 'way' );
+               my $s_name = name_from_list( 'street', $waytag->{$member->{ref}} );
+               next if !$s_name;
+
+               $street_name = $s_name;
+               last;
+
+            }
             next if !$street_name;

             for my $member ( @$members ) {

ось. тут ім"я береться з тегів на першій лінії з роллю street, у якої є якесь ім"я. відповідно, якщо першою зустрінеться вулиця, у якої заданий name, а name:ru - ні, то вся вулиця буде вважатись українською. вже вибачте :slight_smile:
також, якщо вулиця з лівою назвою затесалась у відношення, так і буде.

патч можете передати liosha якщо він буде працювати як треба

собственно поэтому я сразу предлагал брать имя из релейшена…

в вики по поводу отношения street/associatedStreet про обязательность name: optional but recommended
в общем, имя должно браться из улиц, а не самого отношения. а если где-то ни одна улица не именована, или есть улицы с левым именем - это ошибка.

Но тогда надо в каждом релейшене вручную копировать названия улиц с тегов самих улиц. По моему, глупо дублировать информацию вручную, если её можно взять автоматически.

Кстати, поясните мне, идиоту, как работает строка

 my $street_name = name_from_list( 'street', $reltag->{$relation_id} );

Я так понял, что здесь объявляется локальная текстовая переменная $street_name
Потом ей присваивается значение. Но как работает name_from_list я так и не понял. :frowning: И почему там ‘street’, а не ‘name’?

И вообще, почему это всё написано на Perl, в котором я не соображаю? :slight_smile:

UPD:
Щойно закінчив конвертацію Харківської обл. з пропатченим конвертором. Воно працює!!!
Але не зовсім так як хотілося.
Я вказую --namelist label=name:ru,name --namelist place=name:ru,name --namelist street=name:ru,name
Ті будинки, у яких нема addr:street, але вони включені до релейшену, отримали в адресі назву вулиці російською мовою. А ті будинки, які мали addr:street, отримали назву вулиці українською мовою, бо в addr:street прописано українською. Не зважаючи на те, що вони були включені до релейшену.

Наприклад, у Харкові, будинки по вулиці Єлізарова, №4 та №6 включені у один релейшен вулиці Єлізарова. При цьому будинок №4 має тег addr:street, а будинок №6 не має.
В результаті маємо адреси:
“Харьков, Елизарова улица, 4” та “Харьков, Єлізарова вулиця, 6”

Я пригадую, що нібито liosha десь писав, що коли будинок має addr:street, то його конвертор шукає поблизу вулицю з таким самим значенням тегу name, бере з нього локалізовану назву name:ru (або іншу, вказану у конфігах) та приписує цю локалізовану назву в addr:street на будинку. Але чомусь ця функція не працює.

Larry0ua, а нащо треба вводити нову змінну $s_name ?

А ще чомусь конвертор повідомляє про меншу кількість адресованих будинків

З оригінальним конвертором

Processing relations...
  95 turn restrictions
  56382 houses with associated street
  0 transport stops

З пропатченим конвертором

Processing relations...
  95 turn restrictions
  37629 houses with associated street
  0 transport stops

Це що, помилка у конверторі, чи в нас так багато будинків (18753) у недороблених релейшенах у Харкові?

Це цілком правильна поведінка, і мова тут ні при чому. Теґи на об’єкті мають перевагу над теґами з відношення. Тобто, їх можна використовувати для уточнення “успадкованого” значення. Власне, addr:street потрібно видалити з окремих будинків.

Це цілком правильна поведінка, і мова тут ні при чому. Теґи на об'єкті мають перевагу над теґами з відношення.

Так, поведінка правильна.
Але я мав на увазі, що не працює старий “механізм” вибору локалізованих назв вулиць у адресах.
Коли є addr:street якоюсь мовою, а у “польському форматі” треба отримати StreetDesc= іншою мовою.

нова змінна, щоб зробити next якщо вона порожня. можна зробити без неї, звичайно, присвоювати зразу в street_name

name_from_list читає заданий список для street він заданий був name:ru,name, і з відповідного об"єкту бере підходящу назву.

а проблему з addr:street я не чіпав, значить, воно і до мене не працювало.

на рахунок меншої кількості - можете додати перед next if !$street_name; стрічку $street_name = name_from_list( ‘street’, $reltag->{$relation_id} ) if !$street_name; - хай в крайньому випадку заповнює з назви відношення.

Спробую прибрати. Я не профі-програміст, але вважаю, що зайва операція присвоювання у циклі - то не є добре.

О, дякую. Тепер починаю трошки розуміти :slight_smile:

я й не звинувачую. В оригінальній версії така сама проблема.

IMHO, відсутність членів типу street у релейшені - це помилка. І відсутність назв у тих членів - теж помилка. І ці помилки треба виправляти в базі OSM, а не у конверторі. Наявність тисячі таких релейшенів у Харкові - це результат незавершеного імпорту даних dima_ua.
“Причешемо” імпортовані дані - таких помилок не стане.

Однак рядок $street_name = name_from_list( ‘street’, $reltag->{$relation_id} ) if !$street_name; я додам. Нехай буде.

Гм. Щось я нахомутав у скрипті…
Рядок street_name = name_from_list( ‘street’, $reltag->{$relation_id} ) if !$street_name; схоже, не працює, бо кількість будинків така сама, що й без нього.

if ( $flags->{street_relations} ) {
    for my $type ( qw{ street associatedStreet } ) {
        my $list = $relations->{$type};
        next if !$list;

        while ( my ($relation_id, $members) = each %$list ) {
            my $street_name;
            for my $member ( @$members ) {
               next if !( $member->{role} eq 'street' );
               next if !( $member->{type} eq 'way' );
               $street_name = name_from_list( 'street', $waytag->{$member->{ref}} );
               $street_name = name_from_list( 'street', $reltag->{$relation_id} ) if !$street_name;
	       next if !$street_name;

               last;

            }
            next if !$street_name;
            
            for my $member ( @$members ) {
                next if !( $member->{role} ~~ [ 'house', 'address' ] );
                $street{"$member->{type}:$member->{ref}"} = $street_name;
            }
        }
    }
    printf STDERR "  %d houses with associated street\n", scalar keys %street;
}

я мав на увазі перед іншим next if !$street_name; :slight_smile: той, який перед for my $member

Переробив. Тепер працює правильно. А я потроху починаю розуміти логіку роботи програми

if ( $flags->{street_relations} ) { 
    for my $type ( qw{ street associatedStreet } ) {
        my $list = $relations->{$type};
        next if !$list;

        while ( my ($relation_id, $members) = each %$list ) {
            my $street_name;   -   створюємо змінну 
            for my $member ( @$members ) {    перебираємо у циклі всіх членів релейшена
               next if !( $member->{role} eq 'street' );   переходимо до наступного члена, якщо роль не street
               next if !( $member->{type} eq 'way' );    переходимо до наступного члена, якщо тип не way
               $street_name = name_from_list( 'street', $waytag->{$member->{ref}} );  беремо назву вулиці з тегів члена релейшена. Тут, чесно кажучи, я ще не зовсім зрозумів синтаксис. Ну нехай.
               next if !$street_name; переходимо до іншого члена, якщо назву вулиці не чомусь отримали.
               last; Закінчуємо цикл, бо назва вулиці вже знайдена.
            }
	    $street_name = name_from_list( 'street', $reltag->{$relation_id} ) if !$street_name;  якщо серед членів релейшена не знайшли того, кто має роль sreet, тип way та має в тегах назву вулиці, то беремо назву вулиці з тегів релейшена.
            next if !$street_name; якщо й в тегах релейшена не знайшли назву вулиці, то це не релейшен, а якась недороблена гидота. Переходимо до іншого релейшена
            for my $member ( @$members ) { знову перебираємо членів релейшена (якщо вже знаємо назву вулиці)
                next if !( $member->{role} ~~ [ 'house', 'address' ] ); переходимо до іншого члена, якщо роль не house або address
                $street{"$member->{type}:$member->{ref}"} = $street_name; записуємо в теги члена релейшена назву вулиці
            }
        }
    }
    printf STDERR "  %d houses with associated street\n", scalar keys %street;
}