sql - Postgis 重新排序混淆线串 block /max_segment_length(线串)?

标签 sql postgresql postgis multilinestring

我将大约 1000 条路径从某处导入到我的 postgis 数据库到一个线串字段。

(EDIT) 我的 table 是这样的

+---------+---------------+------------------+
| id(int) | name(varchar) | path(LINESTRING) |
+---------+---------------+------------------+
| 123     | foo           | 000002...        |
| 124     | bar           | 000002...        |

我遇到的问题是每条路径都被分成 block ,并且在某些情况下这些 block 混在一起。

假设一条线串在第 50 和 70 点被分割:

  1. 组 block A:1-50 分
  2. 组 block B:51-70 分
  3. 组 block C:71-100 分

当我将其迁移到我的数据库中时,它们混合在一起,因此生成的线串可能会像这样结束:

  1. 组 block A:1-50 分
  2. 组 block C:71-100 分
  3. 组 block B:51-70 分

所以这会产生从 50 跳到 71 和另一个从 100 跳到 51

(EDIT) 当我导入那些分成 block 的路径时,我认为它们是有序的,但事实是有些是混合的,这使得我的一些线串与它们的点有序就像第二个例子。

我希望能够对这些(点) block 重新排序,因此我想构建一个 SQL 查询来检测哪些路径具有混合点,然后我可以手动(使用使用 openlayers 制作的工具)重新排列它们。

希望有一个 SQL 更新查询来解决这个问题,但我认为检测更容易(我假设大约有 5% 或更少的路径有错误)

EDIT3:我认为检测脚本可以检查路径是否包含距离太远的一对连续点。也许从包含最长段的路径中排序路径的 SQL 会很好。

我如何创建一个函数来获取线串中最大线段的长度?

我举个例子: 数据库里是这样的 a bad way

这就是我想要修复它的方式 a good (fixed) way

EDIT4:就像我在 EDIT3 上计划的那样,可以编写一个函数来查找线串中两个连续点之间的最长距离,使用 ST_NPoints() 迭代线串的点。和 ST_PointN() ,然后可以进行查询以对具有最长距离的路径进行排序。这个距离太长的线串很可能会出现所描述的问题。这样我就能够检测到它们并手动修复它们。

检测SQL的结果是这样的:

                                             |ordered by this|
+---------+---------------+------------------+---------------+
| id(int) | name(varchar) | path(LINESTRING) |  msbtcp(int)  |
+---------+---------------+------------------+---------------+
| 123     | foo           | 000002...        | 1000          |
| 124     | bar           | 000002...        | 800           |

*msbtcp 将是函数的结果:max_separation_between_two_consecutive_points(path)

最佳答案

这听起来有点令人费解,但是如果您刚好在线串中两个连续点之间的最大距离之后:

CREATE OR REPLACE FUNCTION max_distance_in_linestring(line geometry) RETURNS float as $BODY$
DECLARE
    i integer;
    n integer;
    d float;
    m float;
BEGIN
    d := 0;
    n := ST_NPoints(line);
    i := 2;
    LOOP
        EXIT WHEN i >= n;
        m := ST_Distance(ST_PointN(line,i-1),ST_PointN(line,i));
        -- use for lon,lats:
        -- m := ST_Distance(ST_PointN(line,i-1)::geography,ST_PointN(line,i)::geography);
        IF m > d THEN
            d := m;
        END IF;
        i := i + 1;
    END LOOP;
    RETURN d;
END;
$BODY$
LANGUAGE plpgsql;

SELECT max_distance_in_linestring('LINESTRING(0 0, 1 1, 2 2)'::geometry);
SELECT max_distance_in_linestring('LINESTRING(0 0, 4 3, 2 2)'::geometry);

您可能希望将 ST_PointN 调用重新转换为::geography 以获取以米为单位的距离。

SQL 是这样的:

SELECT
  name, path 
FROM
  paths
ORDER BY
  max_distance_in_linestring(path) DESC

关于sql - Postgis 重新排序混淆线串 block /max_segment_length(线串)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10126187/

相关文章:

sql - 如何删除父子记录

java - 增加 Java.sql.date/time 的最佳方法是什么?

optimization - PostgreSQL:如何优化我的数据库以存储和查询一个巨大的图形

postgresql - 查找每个组的最近日期并加入所有记录的性能问题

postgresql - 重启 Spring Boot 应用程序后首次调用速度慢

postgresql - 多边形点距其质心的最远距离

sql - st_intersects 与 st_overlaps

mysql - 有没有办法给sql语句指定条件?

ruby-on-rails - 由于空间适配器错误,Heroku 将无法启动

mysql - SQL 内连接性能问题