PostGISで3角形を描画する
忙しい人用:自作関数による3角描画(経度、緯度、外接円の半径)
第1引数の経度、第2引数の緯度で指定された中心点を持つ、第3引数rで指定した半径の円の中にある正三角形を出力します。
create_function_st_triangle.sql
/**
* Create triangle geometry.
* @param lon double precision center point WGS84 SRID:4326
* @param lat double precision WGS84 SRID:4326
* @param r double precision circumradius by the meter
* @return geometry
**/
CREATE OR REPLACE FUNCTION st_triangle( lon double precision, lat double precision , r double precision )
RETURNS geometry
AS 'with t_plist(id,n)as (
values (1, 25 ) , (2, 4 ) , (3, 14 ) ,(4, 25 ) )
SELECT
ST_SetSRID( ST_MakePolygon(ST_MakeLine( array( SELECT geom
FROM
(
SELECT
id, geom
FROM
ST_dumppoints( ST_ExteriorRing( ST_Buffer( ST_POINT( $1 , $2)::geography , $3)::geometry ) ) AS c
, t_plist
WHERE
t_plist.n = path[1]
ORDER BY t_plist.id
) AS a ) ) ) , 4326 );'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
デモ:東京駅を中心とした、三角形の描画
test_st_triangle.sql
SELECT ST_AsText( st_triangle( 139.76719 , 35.6811 ,50) )
UNION
SELECT ST_AsText( st_triangle( 139.76719 , 35.6811 ,100) )
UNION
SELECT ST_AsText( st_triangle( 139.76719 , 35.6811 ,150) )
UNION
SELECT ST_AsText( st_triangle( 139.76719 , 35.6811 ,200) )
PostGISで三角形を作画するには
任意の大きさの作図を実現するST_Bufferの利用
以前の投稿PostGISのST_Bufferで円を描画するで、ST_Bufferで作成した円は、半径に関わらず32角である事が分かりました。そこで、32角の特定の角をピックアップすれば、三角形が作成出来ると考えました。
ST_Bufferの補間点の出力の観察
補間点をQGISで表示して観察してみると、最も東の点から時計回りで出力されいます。
真北に頂点を持つ正三角形を作成するには、「25→4→14→25」の順番で点を結ぶとポリゴンが作成できます。
- 32角から、25と4と14と25を列挙する
with t_plist(id,n)as (
values (1, 25 ) , (2, 4 ) , (3, 14 ) ,(4, 25 ) )
- 円から補間点を抽出し、
t_plist
のn列で指定した番号のポイントを抽出
SELECT
id, geom
FROM
ST_dumppoints( ST_ExteriorRing( ST_Buffer( ST_POINT( $1 , $2)::geography , $3)::geometry ) ) AS c
, t_plist
WHERE
t_plist.n = path[1]
PostGISの関数の簡単な解説
ST_POINT
: 緯度経度からポイント型の地物を作成する
ST_Buffer
: 地物の周りに面を付与する
ST_ExteriorRing
: ポリゴン形状の外枠を線オブジェクトとして出力する
ST_dumppoints
: 地物の補間点を列挙する
関数化
SQLによるストアドファンクション(自作関数)を作成してみます。
PostgreSQLの場合、関数名が同じでも引数と戻り値が異なると、同一名称でも複数個の登録が可能です。
CREATE OR REPLACE FUNCTION 関数名( 引数名 型 )
RETURNS 戻り値の型
AS 'ここにSQLを記述する。 引数は$1で呼び出し可能'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
折角なので、3タイプ程関数を作ってみます。
同じ名称ですが、1つのデータベースに同居可能です。
関数1:緯度、経度、外接円の半径を指定する関数
create_function_st_triangle_1.sql
/**
* Create triangle geometry.
* @param lon double precision center point WGS84 SRID:4326
* @param lat double precision WGS84 SRID:4326
* @param r double precision circumradius by the meter
* @return geometry
**/
CREATE OR REPLACE FUNCTION st_triangle( lon double precision, lat double precision , r double precision )
RETURNS geometry
AS 'with t_plist(id,n)as (
values (1, 25 ) , (2, 4 ) , (3, 14 ) ,(4, 25 ) )
SELECT
ST_SetSRID( ST_MakePolygon(ST_MakeLine( array( SELECT geom
FROM
(
SELECT
id, geom
FROM
ST_dumppoints( ST_ExteriorRing( ST_Buffer( ST_POINT( $1 , $2)::geography , $3)::geometry ) ) AS c
, t_plist
WHERE
t_plist.n = path[1]
ORDER BY t_plist.id
) AS a ) ) ) , 4326 );'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
関数2 :GEOMETRY型と外接円の半径を指定するタイプ
create_function_st_triangle_2.sql
/**
* Create triangle geometry.
* @param center_point geometry
* @param r double precision circumradius by the meter
* @return geometry
**/
CREATE OR REPLACE FUNCTION st_triangle( center_point geometry , r double precision )
RETURNS geometry
AS 'with t_plist(id,n)as (
values (1, 25 ) , (2, 4 ) , (3, 14 ) ,(4, 25 ) )
SELECT
ST_SetSRID( ST_MakePolygon(ST_MakeLine( array( SELECT geom
FROM
(
SELECT
id, geom
FROM
ST_dumppoints( ST_ExteriorRing( ST_Buffer( ST_Transform( $1 , 4326)::geography , $2 )::geometry ) ) AS c
, t_plist
WHERE
t_plist.n = path[1]
ORDER BY t_plist.id
) AS a ) ) ) , 4326 );'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
関数3 :GEOGRAPHY型と外接円の半径を指定するタイプ
create_function_st_triangle_3.sql
/**
* Create triangle geometry.
* @param center_point geography
* @param r double precision circumradius by the meter
* @return geography
**/
CREATE OR REPLACE FUNCTION st_triangle( center_point geography , r double precision )
RETURNS geography
AS 'with t_plist(id,n)as (
values (1, 25 ) , (2, 4 ) , (3, 14 ) ,(4, 25 ) )
SELECT
ST_SetSRID( ST_MakePolygon(ST_MakeLine( array( SELECT geom
FROM
(
SELECT
id, geom
FROM
ST_dumppoints( ST_ExteriorRing( ST_Buffer($1 , $2 )::geometry ) ) AS c
, t_plist
WHERE
t_plist.n = path[1]
ORDER BY t_plist.id
) AS a ) ) ) , 4326 )::geography ;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;