ST_DumpPoints из полигонов с углами

Ответить
VorSer
Интересующийся
Сообщения: 31
Зарегистрирован: 18 июл 2017, 12:26
Репутация: 0

ST_DumpPoints из полигонов с углами

Сообщение VorSer » 22 июл 2019, 21:08

Понадобилось сделать представление в виде точечного слоя из слоя с полигонами, путем изучения интернетов получилось вот это.

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

SELECT
((t1.part || (((t1.dp).path[2] - 1)::text)) || lpad((t1.dp).path[3]::text, 3, '0'::text))::integer AS id,
ST_x((t1.dp).geom) as x,
ST_y((t1.dp).geom) as y
	FROM(
		SELECT DISTINCT ON (zones_pgn.id, ((st_dumppoints(zones_pgn.geom)).geom)) zones_pgn.id AS edge_id,
		zones_pgn.part,
        	ST_DumpPoints(zones_pgn.geom) AS dp
      		FROM konakovskiy.zones_pgn
      		ORDER BY zones_pgn.id, ((ST_DumpPoints(zones_pgn.geom)).geom), ((ST_DumpPoints(zones_pgn.geom)).path[3])) t1
ORDER BY id;
Как ни странно - оно работает, но не хватает одного столбца, а именно угла, образуемого между тремя соседними точками. В ST_Angle я понимаю как указать P2, но откуда взять геометрию P1 и P3 не понимаю. lag/lead не вкурил...
Вопрос, собственно, в том как мне добавить к этой таблице углы?
Квалификация моя околонулевая, поэтому буду благодарен за конкретный рецепт.

trir
Гуру
Сообщения: 5277
Зарегистрирован: 09 апр 2010, 19:30
Репутация: 1013
Ваше звание: просто мимо прохожу
Откуда: Ё-бург

Re: ST_DumpPoints из полигонов с углами

Сообщение trir » 23 июл 2019, 07:06

я бы просто функцию написал бы
https://alastaira.wordpress.com/2011/01 ... eometries/

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

CREATE FUNCTION dbo.SplitMultiGeometry (@MultiGeom geometry)
RETURNS @Table TABLE( Geom geometry )
BEGIN
DECLARE @n int = 1;
WHILE (@n <= @MultiGeom.STNumGeometries())
BEGIN
INSERT INTO @Table VALUES(@MultiGeom.STGeometryN(@n));
SET @n = @n + 1;
END
RETURN
END
GO
@n-1 и @n+1 и обработать граничные случаи

VorSer
Интересующийся
Сообщения: 31
Зарегистрирован: 18 июл 2017, 12:26
Репутация: 0

Re: ST_DumpPoints из полигонов с углами

Сообщение VorSer » 23 июл 2019, 14:41

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

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

CREATE OR REPLACE VIEW konakovskiy.crd AS
 SELECT t3.id,
    t3.geom,
    t3.type,
    t3.name,
    t3.part,
    t3.ring,
    t3.subnum,
    t3.x,
    t3.y,
    t2.delta,
    t2.zu_kn
   FROM ( SELECT ((t1.edge_id || (((t1.dp).path[2] - 1)::text)) || lpad((t1.dp).path[3]::text, 3, '0'::text))::integer AS id,
            (t1.dp).geom AS geom,
            t1.type,
            t1.name,
            t1.part,
            (t1.dp).path[2] - 1 AS ring,
            (t1.dp).path[3] AS subnum,
            st_y((t1.dp).geom) AS x,
            st_x((t1.dp).geom) AS y
           FROM ( SELECT DISTINCT ON (zones_pgn.id, ((st_dumppoints(zones_pgn.geom)).geom)) zones_pgn.id AS edge_id,
                    zones_pgn.part,
                    zones_pgn.type,
                    zones_pgn.name,
                    st_dumppoints(zones_pgn.geom) AS dp
                   FROM konakovskiy.zones_pgn
                  ORDER BY zones_pgn.id, ((st_dumppoints(zones_pgn.geom)).geom), ((st_dumppoints(zones_pgn.geom)).path[3])) t1
          ORDER BY (((t1.edge_id || (((t1.dp).path[2] - 1)::text)) || lpad((t1.dp).path[3]::text, 3, '0'::text))::integer)) t3
     LEFT JOIN ( SELECT t1.id,
            t1.geom,
            round(st_y(t1.geom)::numeric, 2) AS x,
            round(st_x(t1.geom)::numeric, 2) AS y,
            t1.delta,
            t1.zu_kn
           FROM ( SELECT DISTINCT ON (pnt_from_kpt.geom) pnt_from_kpt.geom,
                    pnt_from_kpt.delta,
                    pnt_from_kpt.id,
                    pnt_from_kpt.kn AS zu_kn
                   FROM konakovskiy.pnt_from_kpt
                  WHERE pnt_from_kpt.delta > 0::numeric
                  ORDER BY pnt_from_kpt.geom, pnt_from_kpt.delta) t1
          ORDER BY t1.id) t2 ON st_equals(t2.geom, t3.geom);
В результате получается вполне устраивающая меня таблица в которой есть координаты каждой точки, а в случае если эта точка присутствует в КПТ - указывается еще погрешность её определения и номер участка откуда оно взялось, плюс динамически меняется в случае, если я редактирую полигон, что важно.
Оно вроде и корявое, и вероятно его можно оптимизировать, но у меня там 8 полигонов и 600 точек... 260-280 msec в моих условиях совершенно не критично.
Была мысль для красоты определить углы в каждом из узлов и в зависимости от масштаба показывать только те, где угол отличается от 180 более чем на 30/45/60 градусов.

trir
Гуру
Сообщения: 5277
Зарегистрирован: 09 апр 2010, 19:30
Репутация: 1013
Ваше звание: просто мимо прохожу
Откуда: Ё-бург

Re: ST_DumpPoints из полигонов с углами

Сообщение trir » 23 июл 2019, 14:46

можно сделать так

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

CREATE FUNCTION dbo.SplitMultiGeometry (@MultiGeom geometry)
RETURNS @Table TABLE( float angle )
BEGIN
DECLARE @n int = 1;
WHILE (@n <= @MultiGeom.STNumGeometries())
BEGIN
INSERT INTO @Table VALUES(ST_Angle(@MultiGeom.STGeometryN(@n-1), @MultiGeom.STGeometryN(@n), @MultiGeom.STGeometryN(@n+1)));
SET @n = @n + 1;
END
RETURN
END
GO

VorSer
Интересующийся
Сообщения: 31
Зарегистрирован: 18 июл 2017, 12:26
Репутация: 0

Re: ST_DumpPoints из полигонов с углами

Сообщение VorSer » 23 июл 2019, 15:16

Попробовал, PgAdmin на это ответил мне:

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

ERROR:  syntax error at or near "@"
LINE 1: CREATE FUNCTION dbo.SplitMultiGeometry (@MultiGeom geometry)
                                                ^
SQL state: 42601
Character: 41

trir
Гуру
Сообщения: 5277
Зарегистрирован: 09 апр 2010, 19:30
Репутация: 1013
Ваше звание: просто мимо прохожу
Откуда: Ё-бург

Re: ST_DumpPoints из полигонов с углами

Сообщение trir » 23 июл 2019, 15:31

Это синтаксис MS SQL Server

VorSer
Интересующийся
Сообщения: 31
Зарегистрирован: 18 июл 2017, 12:26
Репутация: 0

Re: ST_DumpPoints из полигонов с углами

Сообщение VorSer » 23 июл 2019, 19:07

trir писал(а):
23 июл 2019, 15:31
синтаксис MS SQL Server
Скажите, а как это будет выглядеть в PostgreSQL?)
Вообще я думал о чем-то вроде этого:

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

(SELECT ST_Angle(p3.l_geom,p3.geom,p3.p_geom)
	 FROM (SELECT
		   lead(geom) OVER (ORDER BY id) l_geom,
		   geom,
		   lag(geom) OVER (ORDER BY id) p_geom
		   FROM t3 ORDER BY id 
		   ) p3
	) AS angle
	
Только это не работает, машина говорит: "relation "t3" does not exist", подозреваю из-за того, что t3 алиас подзапроса...

trir
Гуру
Сообщения: 5277
Зарегистрирован: 09 апр 2010, 19:30
Репутация: 1013
Ваше звание: просто мимо прохожу
Откуда: Ё-бург

Re: ST_DumpPoints из полигонов с углами

Сообщение trir » 24 июл 2019, 06:56


Ответить

Вернуться в «PostGIS/PostgreSQL»

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

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