Как определить и упростить точечные кластеры в отношении времени в PostGIS?

11

Я только начал работать с пространственными базами данных и хочу написать запрос SQL (PostGIS) для автоматического обобщения необработанных GPS-треков (с фиксированной частотой отслеживания). Первое, на чем я работаю, - это запрос, который идентифицирует точки остановки в форме запроса, такого как «x точек на расстоянии y метров», чтобы заменить массивные облака точек репрезентативными точками. Я уже понял, чтобы привязать точки на определенном расстоянии и сосчитать привязанные. На рисунке ниже можно увидеть примерный трек (маленькие черные точки) и центры привязанных точек в виде цветных кружков (размер = количество привязанных точек).

введите описание изображения здесь

CREATE table simplified AS 
 SELECT count(raw.geom)::integer AS count, st_centroid(st_collect(raw.geom)) AS center
   FROM raw
  GROUP BY st_snaptogrid(raw.geom, 500, 0.5)
  ORDER BY count(raw.geom) DESC;

Я был бы столь же доволен этим решением, но есть проблема времени: представив дорожку в виде дорожки полного дня в городе, человек может вернуться в места, которые уже посещал ранее. В моем примере темно-синий круг представляет дом человека, который он посетил дважды, но мой запрос, конечно, игнорирует это.

В этом случае сложный запрос должен собирать только точки с непрерывными временными метками (или идентификаторами), так что он будет производить две репрезентативные точки здесь. Моей первой идеей была модификация моего запроса к 3d-версии (время как третье измерение), но, похоже, она не работает.

У кого-нибудь есть советы для меня? Я надеюсь, что мой вопрос понятен.


Спасибо за идею линии. Я понял, как сделать и упростить линейную линию, как вы можете видеть на скриншоте ниже (точки - это исходные точки). введите описание изображения здесь Что мне еще нужно, так это определить места отдыха (> x точек в радиусе <x метров), в идеале как одну точку с временем прибытия и уходом ... какие-нибудь другие идеи?

Berlin_J
источник
2
Тебе действительно нужны очки для других целей? В противном случае может показаться, что вы просто создаете линии из точек, а затем упрощаете / обобщаете эти линии.
Энтони-GISCOE-
2
Это увлекательная проблема. Вы можете найти некоторые идеи по существу того же вопроса, который был задан на сайте Mathematica по адресу mathematica.stackexchange.com/questions/2711 . Не все ответы используют временное измерение данных (но мой использует :-).
whuber
@ Anthony-GISCOE - это интересный подход. В случае необходимости точечных объектов, новые могут быть созданы из вершин обобщенных линий или вдоль линий, как здесь gis.stackexchange.com/questions/27102/… . Я знаю, это все еще не оригинальные пункты!
andytilia
@ Энтони: мне абсолютно нужны точки «репрезентации» любого неподвижного места и, по крайней мере, время начала и окончания ...
Berlin_J
1
и было бы очень полезно иметь постгис-решение :)
Berlin_J

Ответы:

4

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

В некоторых случаях вам даже не нужно сохранять все точки, поэтому вы можете выполнить фильтрацию перед сохранением данных точек, например, когда объект не перемещается, не сохраняйте его. Вы можете применить DouglasPeucker или другой базовый фильтр, прежде чем добавлять точки в БД. Также некоторые провайдеры GPS (например, Android Location API) могут автоматически выполнять начальную фильтрацию по времени и минимальному расстоянию. В некоторых случаях вы сохраняете дубликаты данных: предварительный фильтр для быстрой визуализации и полный журнал для архива. Обычное хранение довольно дешево в наши дни.

JaakL
источник
3

Тем временем я нашел решение своей проблемы:

Сначала я определил «тип расстояния» для каждой точки. Если точка ближе, чем на x метров к следующей точке, она определяется как «стоп», в противном случае как «движение». Затем я запустил оконную функцию следующим образом:

     SELECT t1.id, t1.dist_type, t1."time", t1.the_geom, t1.group_flag, sum(t1.group_flag) OVER (ORDER BY t1.id) AS group_nr
FROM ( SELECT distances.id, distances.the_geom, distances."time", distances.dist_type, 
                CASE
                    WHEN lag(distances.dist_type) OVER (ORDER BY distances.id) = distances.dist_type THEN NULL::integer
                    ELSE 1
                END AS group_flag
           FROM distances) t1;

Полученная таблица выглядит следующим образом:

введите описание изображения здесь

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

Berlin_J
источник