Postgresql PostGIS:一组共线线段的交点,带计数

Postgresql PostGIS:一组共线线段的交点,带计数,postgresql,gis,postgis,Postgresql,Gis,Postgis,我有一组共线线段(可能相互不相交、包含或重叠) 我想创建一组新的线段,其中线段不相交或接触(不重叠),并且每个线段都有覆盖它的原始线段的计数 例如,假设原始集为(为便于说明,绘制为非共线): 所需的新设置为: A-------C---E-----F-----B-----------D G-------------H-------J 1 2 3 2 1 1 1 (只有点坐标才重要,新集合不

我有一组共线线段(可能相互不相交、包含或重叠)

我想创建一组新的线段,其中线段不相交或接触(不重叠),并且每个线段都有覆盖它的原始线段的计数

例如,假设原始集为(为便于说明,绘制为非共线):

所需的新设置为:

A-------C---E-----F-----B-----------D      G-------------H-------J
    1     2    3     2        1                    1         1
(只有点坐标才重要,新集合不与旧集合共享点对象)

如何使用PostGIS实现这一点

相关问题:假设我从一个线段表开始,而不是全部共线,我如何编写将共线线段分组在一起的整个查询,然后将解决方案应用于我的第一个问题

谢谢你的帮助

设置(用于以后的查询):

注:

  • 我故意改变你的D点和C点来证明向量求反的必要性
  • P-L
    行与示例行平行(但不共线)
  • X-Y
    行与其他行无关
  • 下面的解决方案显然不起作用,如果您的线串有两个以上的点,并且这些点不在同一条线上(因此当单个线串不直时)
聚合函数可以拆分共线字符串。您只需计算包含这些内容的行数

然而,按共线性分组并不是那么简单。我没有为此找到任何现成的解决方案,但您可以计算它(这还不会计算计数):

要计算计数,
JOIN
再次连接原始数据,其中拆分的行包含在()原始行中:

select    ST_AsText(splitted_line), count(line_data)
from      (select   ST_Multi(ST_Union(line_data)) ml
           from     lines
           group by (
             select case
               when ST_SRID(s) <> ST_SRID(e) then row(ST_SRID(s), s, null)
               when ST_X(s) = ST_X(e) then row(ST_SRID(s), ST_SetSRID(ST_MakePoint(ST_X(s), 1.0), ST_SRID(s)), null)
               when ST_Y(s) = ST_Y(e) then row(ST_SRID(s), ST_SetSRID(ST_MakePoint(1.0, ST_Y(e)), ST_SRID(s)), null)
               else (
                 select  row(
                           ST_SRID(s),
                           (select case
                              when ST_Y(rv) < 0
                              then ST_SetSRID(ST_MakePoint(-ST_X(rv), -ST_Y(rv)), ST_SRID(s))
                              else rv
                            end), -- normalized vector (negated when necessary, but same for all parallel lines)
                           (ST_X(e) * ST_Y(s) - ST_X(s) * ST_Y(e)) / (ST_X(e) - ST_X(s)) -- solution of the linear equaltion, where x=0
                         )
                 from    coalesce(1.0 / nullif(ST_Distance(s, e), 0), 0) dmi, -- distance's multiplicative inverse
                         ST_TransScale(e, -ST_X(s), -ST_Y(s), dmi, dmi) rv -- raw vector (translated and scaled)
               )
             end
             from   ST_StartPoint(line_data) s,
                    ST_EndPoint(line_data) e)) al,
          generate_series(1, ST_NumGeometries(ml)) i,
          ST_GeometryN(ml, i) splitted_line
left join lines on ST_Contains(line_data, splitted_line)
group by  splitted_line

让我们一次只问一个问题,同时发布您的表格和一些示例数据,请回答。现在,我尝试使用真实数据(来自OpenStreetMap的路由)运行第一个SQL查询,但收到错误:“错误:对混合SRID几何体的操作SQL状态:XX000”。数据库中EPSG:4326坐标系中的线性几何。如何修复此错误?GeoJSON格式的示例数据。谢谢@您不能将SRID与f.ex混合,因此如果您有数据。SRID=4326,您应该将
ST_MakePoint
调用包装在一个内部。@我已经更新了我的解决方案,使其也能执行SRID。但我必须说:你的样本数据看起来不像只有直线。解决方案仅适用于这些问题。
create table lines (
  id        serial               primary key,
  label     text                 not null,
  line_data geometry(linestring) not null
);

insert into lines(label, line_data)
values ('A-B', ST_MakeLine(ST_MakePoint(-3, -6), ST_MakePoint( 1,  2))),
       ('D-C', ST_MakeLine(ST_MakePoint( 2,  4), ST_MakePoint(-2, -4))),
       ('E-F', ST_MakeLine(ST_MakePoint(-1, -2), ST_MakePoint( 0,  0))),
       ('G-H', ST_MakeLine(ST_MakePoint( 3,  6), ST_MakePoint( 4,  8))),
       ('I-J', ST_MakeLine(ST_MakePoint( 4,  8), ST_MakePoint( 5, 10))),
       ('P-L', ST_MakeLine(ST_MakePoint( 1,  0), ST_MakePoint( 2,  2))),
       ('X-Y', ST_MakeLine(ST_MakePoint( 2,  2), ST_MakePoint( 0,  4)));
select   string_agg(label, ','), ST_AsText(ST_Multi(ST_Union(line_data)))
from     lines
group by (
  select case
           when ST_SRID(s) <> ST_SRID(e) then row(ST_SRID(s), s, null)
           when ST_X(s) = ST_X(e) then row(ST_SRID(s), ST_SetSRID(ST_MakePoint(ST_X(s), 1.0), ST_SRID(s)), null)
           when ST_Y(s) = ST_Y(e) then row(ST_SRID(s), ST_SetSRID(ST_MakePoint(1.0, ST_Y(e)), ST_SRID(s)), null)
           else (
             select  row(
                       ST_SRID(s),
                       (select case
                          when ST_Y(rv) < 0
                          then ST_SetSRID(ST_MakePoint(-ST_X(rv), -ST_Y(rv)), ST_SRID(s))
                          else rv
                        end), -- normalized vector (negated when necessary, but same for all parallel lines)
                       (ST_X(e) * ST_Y(s) - ST_X(s) * ST_Y(e)) / (ST_X(e) - ST_X(s)) -- solution of the linear equaltion, where x=0
                     )
             from    coalesce(1.0 / nullif(ST_Distance(s, e), 0), 0) dmi, -- distance's multiplicative inverse
                     ST_TransScale(e, -ST_X(s), -ST_Y(s), dmi, dmi) rv -- raw vector (translated and scaled)
           )
         end
  from   ST_StartPoint(line_data) s,
         ST_EndPoint(line_data) e
)
X-Y                 | MULTILINESTRING((2 2,0 4))
P-L                 | MULTILINESTRING((1 0,2 2))
E-F,A-B,I-J,G-H,D-C | MULTILINESTRING((-3 -6,-2 -4),(-2 -4,-1 -2),(-1 -2,0 0),(0 0,1 2),(2 4,1 2),(3 6,4 8),(4 8,5 10))
select    ST_AsText(splitted_line), count(line_data)
from      (select   ST_Multi(ST_Union(line_data)) ml
           from     lines
           group by (
             select case
               when ST_SRID(s) <> ST_SRID(e) then row(ST_SRID(s), s, null)
               when ST_X(s) = ST_X(e) then row(ST_SRID(s), ST_SetSRID(ST_MakePoint(ST_X(s), 1.0), ST_SRID(s)), null)
               when ST_Y(s) = ST_Y(e) then row(ST_SRID(s), ST_SetSRID(ST_MakePoint(1.0, ST_Y(e)), ST_SRID(s)), null)
               else (
                 select  row(
                           ST_SRID(s),
                           (select case
                              when ST_Y(rv) < 0
                              then ST_SetSRID(ST_MakePoint(-ST_X(rv), -ST_Y(rv)), ST_SRID(s))
                              else rv
                            end), -- normalized vector (negated when necessary, but same for all parallel lines)
                           (ST_X(e) * ST_Y(s) - ST_X(s) * ST_Y(e)) / (ST_X(e) - ST_X(s)) -- solution of the linear equaltion, where x=0
                         )
                 from    coalesce(1.0 / nullif(ST_Distance(s, e), 0), 0) dmi, -- distance's multiplicative inverse
                         ST_TransScale(e, -ST_X(s), -ST_Y(s), dmi, dmi) rv -- raw vector (translated and scaled)
               )
             end
             from   ST_StartPoint(line_data) s,
                    ST_EndPoint(line_data) e)) al,
          generate_series(1, ST_NumGeometries(ml)) i,
          ST_GeometryN(ml, i) splitted_line
left join lines on ST_Contains(line_data, splitted_line)
group by  splitted_line
LINESTRING(-3 -6,-2 -4) | 1
LINESTRING(-2 -4,-1 -2) | 2
LINESTRING(-1 -2,0 0)   | 3
LINESTRING(0 0,1 2)     | 2
LINESTRING(2 2,0 4)     | 1
LINESTRING(1 0,2 2)     | 1
LINESTRING(2 4,1 2)     | 1
LINESTRING(3 6,4 8)     | 1
LINESTRING(4 8,5 10)    | 1