Вычислить угол внешних колец PostGIS (полигоны и мультиполигоны)

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

ПРИМЕР ДАННЫХ:

CREATE TABLE poly_and_multipoly ( "id" SERIAL NOT NULL PRIMARY KEY, "name" char(1) NOT NULL, "the_geom" geometry NOT NULL ); -- add data, A is a polygon, B is a multipolygon INSERT INTO poly_and_multipoly (name, the_geom) VALUES ( 'A', 'POLYGON((7.7 3.8,7.7 5.8,9.0 5.8,7.7 3.8))'::geometry ), ( 'B', 'MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))'::geometry ); 

У меня есть таблица многополигонов и многоугольников, и я пытаюсь рассчитать внутренние углы внешних колец в таблице (то есть без внутренних колец …), используя ST_Azimuth . Есть ли способ изменить прилагаемый запрос на использование ST_Azimuth на sp и ep linestrings?

  SELECT id, name, ST_AsText( ST_MakeLine(sp,ep) ) FROM -- extract the endpoints for every 2-point line segment for each linestring (SELECT id, name, ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep FROM -- extract the individual linestrings (SELECT id, name, (ST_Dump(ST_Boundary(the_geom))).geom FROM poly_and_multipoly ) AS linestrings ) AS segments; 1;"A";"LINESTRING(7.7 3.8,7.7 5.8)" 1;"A";"LINESTRING(7.7 5.8,9 5.8)" 1;"A";"LINESTRING(9 5.8,7.7 3.8)" 2;"B";"LINESTRING(0 0,4 0)" 

Использование функции ST_Azimuth в примере aengus дает ошибку, потому что вы не можете использовать два параметра generate_series в качестве параметров для одной функции. Если вы используете значения ep / sp в другом подзапросе, тогда у вас не будет никаких проблем.

Вот мое решение:

 -- 3.- Create segments from points and calculate azimuth for each line. -- two calls of generate_series for a single function wont work (azimuth). select id, name, polygon_num, point_order as vertex, -- case when point_order = 1 then last_value(ST_Astext(ST_Makeline(sp,ep))) over (partition by id, polygon_num) else lag(ST_Astext(ST_Makeline(sp,ep)),1) over (partition by id, polygon_num order by point_order) end ||' - '||ST_Astext(ST_Makeline(sp,ep)) as lines, -- abs(abs( case when point_order = 1 then last_value(degrees(ST_Azimuth(sp,ep))) over (partition by id, polygon_num) else lag(degrees(ST_Azimuth(sp,ep)),1) over (partition by id, polygon_num order by point_order) end - degrees(ST_Azimuth(sp,ep))) -180 ) as ang from (-- 2.- extract the endpoints for every 2-point line segment for each linestring -- Group polygons from multipolygon select id, name, coalesce(path[1],0) as polygon_num, generate_series(1, ST_Npoints(geom)-1) as point_order, ST_Pointn(geom, generate_series(1, ST_Npoints(geom)-1)) as sp, ST_Pointn(geom, generate_series(2, ST_Npoints(geom) )) as ep from ( -- 1.- Extract the individual linestrings and the Polygon number for later identification select id, name, (ST_Dump(ST_Boundary(the_geom))).geom as geom, (ST_Dump(ST_Boundary(the_geom))).path as path -- To identify the polygon from poly_and_multipoly ) as pointlist ) as segments; 

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

Поскольку sqlfiddle не поддерживает PostGIS, я загрузил этот пример с некоторым дополнительным кодом в github здесь

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

  SELECT id, name, ST_AsText( ST_MakeLine(sp,ep) ), az FROM -- extract the endpoints for every 2-point line segment for each linestring (SELECT id, name, ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep, ST_Azimuth(ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)), ST_PointN(geom, generate_series(2, ST_NPoints(geom) ))) as az FROM -- extract the individual linestrings (SELECT id, name, (ST_Dump(ST_Boundary(the_geom))).geom FROM poly_and_multipoly ) AS linestrings ) AS segments;