Запрос PostGis

Mapserver, GeoServer, MapGuide, Google и другое ПО для веб-картографии
Ответить
Warden
Интересующийся
Сообщения: 25
Зарегистрирован: 16 сен 2015, 16:43
Репутация: 7
Откуда: Королёв

Запрос PostGis

Сообщение Warden » 31 май 2016, 09:44

Доброго времени суток, ребят!
Пытаюсь решить такую задачу и что то не нахожу в PostGis такой функции, может надо как то самому сложными запросами сделать. В общем так, есть таблица с точками. Для начало выбираются точки с большой вероятностью из тех, что есть, затем надо их объединить, если они находятся близко.
ПРИМЕР
Определяем вероятность пожара с процентом вероятности больше 80%.

Код: Выделить всё

SELECT * FROM hotspots where probability >80;
Нам выдало 10 точек с данными: id, температура, высота пикселя (км), ширина пикселя (км), вероятность, мощность, геометрия(точка,4326), дата получения.
Далее, допустим выбираем самую интенсивную точку:

Код: Выделить всё

SELECT * FROM hotspots WHERE power=(SELECT MAX(power) FROM hotspots where probability >80);
Получаем одну точку. Вот теперь нужно то, чего я не могу сделать и не соображу как. Надо по идеи очертить вокруг точки зону, допустим радиусом в 4 км. Если точки, у которых вероятность больше 80% попадают в эту зону, исключить их из запроса. После того как это сделано, из оставшихся точек (по идеи самая интенсивная точка тоже уже должна выйти из списка) проделываем ту же процедуру, итак пока не уберем все точки.
Цель задачи: Делаю систему оповещения о пожарах и часто так бывает, что горячие точки находятся на расстоянии пары минут и чтобы бедному пользователю не прилетало 6-7 оповещений с почти одинаковыми координатами надо убрать близкие точки из них оставить только одну.
Если есть идеи как то реализовать подскажите, пожалуйста! Может это и не PostGis'ом делать, а на php написать, просто выбирать все точки с вероятностью более 80% и дальше уже какими то формулами вычислять это. Буду приветствовать все варианты решения такой задачи, но желательно сделать это на уровне БД.

lenny314156
Интересующийся
Сообщения: 35
Зарегистрирован: 27 июл 2013, 21:47
Репутация: 6

Re: Запрос PostGis

Сообщение lenny314156 » 31 май 2016, 11:32

Возможно, помогут функции

Код: Выделить всё

ST_Buffer(geometry, double, [integer])
Возвращает геометрию, все точки которой находятся на меньшем или равном расстоянии, чем заданное, от заданной геометрии. 

Код: Выделить всё

ST_Within(geometry A, geometry B)
Возвращает 1 (TRUE), если геометрия A находится "пространственно внутри" геометрии B.
т.е. первой "рисуете" круг с заданным радиусом вокруг нужной точки, а с помощью второй определяете точки, которые попадают в этот круг...

Warden
Интересующийся
Сообщения: 25
Зарегистрирован: 16 сен 2015, 16:43
Репутация: 7
Откуда: Королёв

Re: Запрос PostGis

Сообщение Warden » 31 май 2016, 12:03

Да, я читал вот эту вашу статью Вашу статью и понял, что действовать нужно так, но что-то не смог написать адекватный запрос, то там, то сям, ругается). Можете написать как должны выглядеть SQL-запросы? И вот еще не совсем понял, как мне задать радиус именно в метрах, а не в чем либо другом? Или это зависит от того, как задана точка?

Warden
Интересующийся
Сообщения: 25
Зарегистрирован: 16 сен 2015, 16:43
Репутация: 7
Откуда: Королёв

Re: Запрос PostGis

Сообщение Warden » 31 май 2016, 17:04

Вопрос можно снимать. Попозже выложу как это реализовано.

Warden
Интересующийся
Сообщения: 25
Зарегистрирован: 16 сен 2015, 16:43
Репутация: 7
Откуда: Королёв

Re: Запрос PostGis

Сообщение Warden » 01 июн 2016, 16:29

Как и обещал скидываю решение. Есть таблица hotspots в которой есть поля id, temperature, power, probability И другие. Далее разработанный скрипт:

Код: Выделить всё

#!/usr/bin/php
<?php
$dbconn=pg_connect("host=***** port=**** dbname=***** user=***** password=****") or die('Could not connect' . pg_last_error());
$createTempTableQuery = "CREATE TEMP  TABLE intensive_hotspots AS (SELECT * FROM hotspots WHERE probability > 80);";
$nearPointsQuery = "CREATE TEMP  TABLE near_point AS (SELECT f.id as f_id, f.power AS f_power, s.id AS s_id, s.power AS s_power,
 ST_Distance_Sphere(f.the_geom, s.the_geom)  FROM intensive_hotspots f, intensive_hotspots s WHERE ST_Distance_Sphere(f.the_geom, s.the_geom) < 2000 and f.id<>s.id AND f.id <s.id);";
pg_query($createTempTableQuery);
pg_query($nearPointsQuery);
$selectQuery = "SELECT * FROM near_point;";
$result = pg_query($selectQuery);
while($notice[]=pg_fetch_row($result));
array_pop($notice);
$delete_point = array();
$true_point = array();
$length_array = count($notice)-1;
for ($i=0; $i<=$length_array;$i += $count_i){
        $count_i = 0;
        $length_small_array = count($notice[$i]);
        $near_point_array = array(array());
        for ($k=0; $k<$length_small_array; $k++){
                $near_point_array[0][$k]=$notice[$i][$k];
        }
        for ($j=$i+1; $j<=$length_array;$j++){
                if ($notice[$i][0] == $notice[$j][0]){
                        for ($k=0; $k<$length_small_array; $k++){
                                $near_point_array[$count_i+1][$k]=$notice[$j][$k];
                        }
                        $count_i=$count_i+1;
                } else {
                        break;
                }
        }
        $true = 0;
        $true_1_i;
        $true_2_i;
        for ($j=0; $j<count($near_point_array);$j++){
                $a = $near_point_array[$j][1];
                $b = $near_point_array[$j][3];
                if ($a >= $b){
                        array_push($delete_point,$near_point_array[$j][2]);
                        $max = $a;
                        $max_1_i = $j;
                        $max_2_i = 0;
                } else {
                        array_push($delete_point,$near_point_array[$j][0]);
                        $max = $b;
                        $max_1_i = $j;
                        $max_2_i = 2;
                }
                if ($true < $max){
                        $true = $max;
                        $true_1_i = $max_1_i;
                        $true_2_i = $max_2_i;
                }
        }
        array_push($true_point,$near_point_array[$true_1_i][$true_2_i]);
        $count_i = $count_i+1;
}
$createTempDeletePointTable = "CREATE TEMP TABLE delete_point (id int);";
pg_query($createTempDeletePointTable);
for ($i=0; $i<count($delete_point); $i++){
        pg_query("INSERT INTO delete_point VALUES('$delete_point[$i]');");
}
$truePointQuery = "SELECT f.id, temperature,height_size, width_size, probability, power, the_geom, time_recieve FROM intensive_hotspots AS f WHERE NOT EXISTS (SELECT 1 FROM delete_point WHERE f.id=delete_point.id);";
$r = pg_query($truePointQuery);
pg_close($dbconn);
?>

Ответить

Вернуться в «Веб-картография»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя