Конвертер OSM -> MP

Блин хочу конвертнуть но ничего не выходит с этим Перлом.
на первой странице написано:

Для работы необходим Perl
И должны быть установлены модули Template-toolkit, Getopt::Long

  • Ну установил я ActivePerl-5.10.0.1001-MSWin32-x86-283495
  • Скачал Template-Toolkit-2.22 (а как это устанавливать и куда?) скопировал в папку c:\Perl\ , запустил Makefile.PL , понажимал Y , что то установилось
  • нашел в инете модуль Long.pm (77.3 кб) и скопировал в папку c:\Perl\lib\Module\
  • в командной строке вписал osm2mp.pl map.osm > map.mp (map.osm это переименованный map.xml)
    и получил какуюто ошибку 21
    Короче объясните чайнику, что я нето сделал?
    И может кто-нибудь выложит эти Template-toolkit и Getopt::Long здесь? А то запарился в инете искать.

Ну коль все просто, тогда так:
PolygonTree.pl

#!/usr/bin/perl -w
use PolygonTree;

my @poly;
while (<STDIN>) {
    chop;
    if ($_ eq '') {
        last;
    } else {
        push @poly, [split];
    };
};

# создаём объект
my $bound = PolygonTree->new(\@poly);

$|++; # включаем autoflush чтобы вывод отдавался сразу
while (<STDIN>) {
    chop;
    # проверяем вхождение
    if ($bound->contains([split])) {
        print "Y\n";
    } else {
        print "N\n";
    };
};

PolygonTree.php

<?php
class PolygonTree {
    private $pipes;
    function __construct($poly) {
        $descriptorspec = array(
               0 => array("pipe", "r"),
               1 => array("pipe", "w"),
            2 => array("pipe", "w")
        );
        $this->process = proc_open('./PolygonTree.pl', $descriptorspec, $this->pipes);
        
        foreach ($poly as $p) {
            fwrite($this->pipes[0], join(' ', $p) . "\n");
        };
        fputs($this->pipes[0], "\n");
    }
    function contains($point) {
        fputs($this->pipes[0], join(' ', $point). "\n");
        $r = fgets($this->pipes[1]);
        return substr($r, 0, 1) == 'Y'? True : False;
    }
    function __destruct() {
        fclose($this->pipes[0]);
        fclose($this->pipes[1]);
        fclose($this->pipes[2]);
    }
}

$pt = new PolygonTree(array(
    array(1,1),
    array(1,2),
    array(2,2),
    array(2,1),
    array(1,1)    
));

var_dump($pt->contains(array(0.5,0.5)));
var_dump($pt->contains(array(1.5,1.5)));
?>

В виндах могут быть проблемы из за другого переноса строк и в proc_open, может быть по другому надо будет написать.
Что будет по производительности - непонятно.

liosha, в строку 25 вроде как закралась синтаксическая ошибка: unless $chain_ref->[0] ~~ $chain_ref->[-1];
Наверное вместо ~~ имелось ввиду == ? Мой перл такого оператора не знает.

Еще у GPC лицензия плохая, не совместимая с GPL. А с geos-ом, на котором я так понимаю postgis бегает мутить никто не пробовал?

Нет, там именно ~~ (smart match): http://perldoc.perl.org/perlsyn.html#Smart-matching-in-detail
Возможно, надо его как-то отдельно подключать.

Тонкостями лицензий пока не интересовался, а другой библиотеки для клипа не нашёл.

SegMar,
запусти ppm.bat из Perl/bin и ставь им

UPD.
Теперь конвертация Московской области с обрезкой по текущей границе (7760 точек) занимает ~45 минут, было больше часа. Основные тормоза вроде как из-за попыток обрезки каждого полигона, а домиков уже немало. :slight_smile:
Как это эту обрезку соптимизировать - пока непонятно

Просто нужен 5.10, а я как-то с 5.8 жил и не тужил. Ясно в общем.

Спасибо! На следующей неделе буду пробовать.

Добавил грубую проверку на попадание полигона в область - метод contains_polygon_rough.
Выдаёт 1 если попадает, 0 - если нет, undef - “c ходу непонятно”.

Лежит там же: http://gpsmapsearch.com/osm/PolygonTree.pm

Теперь та же Москва с тем же полигоном (7760 точек) собирается за 2 минуты 15 секунд
Жить можно :sunglasses:

А как насчет других регионов? Выкачивать “полные” описывающие прямоугольники?

По-хорошему надо бы поднять копию базы и уже из неё вытаскивать куски с нужными регионами.
А качать большие регионы через api не есть хорошо.

База будет. И, надеюсь, мне удастся присобачить к ней твою библиотеку и обертку, сделанную уважаемым Aleksandr Dezhin. Тогда проблем вытаскивать из нее куски не будет. Осталось закончить ремонт и вернуться жить домой :slight_smile:

Сегодня обновил карту Москвы для навитела - пропал адресный поиск в Королеве и Долгопрудном. До этого поиск работал - сам обрисовывал границу Долгопрудного и после этого тестировал в навителе.

Границу Долгопрудного я почикал, в смысле немного поправил и преобразовал в relation type=boundary, чего конвертер похоже не понимает. Наверное поэтому кто-то сделал Москве второй контур из одного полигона. Королев вроде как не трогал.

Да похоже дело в этом, мудрёные отношения конвертер не понимает. Границы долгопрудного я рисовал по простому - через place=town и королев если мне память не изменяет был сделан также.

Каюсь, Королев наверное тоже я почикал, когда из него Юбилейный вырезал.

Москву восстанавливал я :sunglasses:

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

А вот сделать обрезку карты по релейшену - о таком подумываю.

Кстати, да только сегодня подумывал предложить. :slight_smile: Ибо сейчас релейшенами границы всех субъектов прорисованы. А конвертер распознает только Адыгею, т.к. ее границы я одним полигоном сделал. :slight_smile:

Ну так что мешает сделать osm2mp первым таким софтом ? :wink:
Например собирать мультиполигоны если в наличии все члены (а иначе ругаться в лог и делать то же что и сейчас - т.е ничего)?
Кстати, а какая поддержка целостности релейшенов подразумевается?
Так получение всех членов есть в API и поддерживается JOSM’ом.

zgremlin,
osm2mp НЕ работает с базой, а получает готовый файл. И вот в этом файле половины мемберов релейшена запросто может не хватать, соответственно и границу города восстановить не получится. А веи почти всегда присутствуют целиком.

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

А зачем столько лишнего гемору, когда правильнее будет просто иметь в базе нужный полигон?

В любом случае, сейчас API целостность релейшенов не поддерживает (целостность - это выдача всех мемберов того релейшена, который попал в bbox). Вот когда будет - тогда будет смысл это обсуждать.