自作MySQL spatial functions plugin の関数を、ひとつひとつ検証しながら紹介してくシリーズ。第(もう数えられなくなった)段。
sakaik.hateblo.jp
STX_Translate(geom, dx, dy)
ジオメトリを、指定した座標分だけ平行移動する関数です。測地系の設定によらず、dxが経度(右方向)、dyが緯度(上方向)です。
個人的にはそれが気持ち悪かったので、lat-lon(緯度-経度)の順序で与えらる独自関数、STX_Translate_latlon(geom, lat, lon) も作成しました。
動作紹介
- ポリゴンの平行移動。経度に0.3、緯度に0.05を加えたぶんだけ平行移動します。
mysql> SET @g1=ST_GeomFromText('POLYGON((35 135, 35.5 135, 35.3 135.5, 35 135.5, 35 135))',6668);
mysql> SELECT ST_AsText(CAST(@g1 AS POLYGON)),
-> ST_AsText(CAST(STX_Translate(@g1, 0.3, 0.05) AS POLYGON));
+-------------------------------------------------------+-------------------------------------------------------------------------------------+
| ST_AsText(CAST(@g1 AS POLYGON)) | ST_AsText(CAST(STX_Translate(@g1, 0.3, 0.05) AS POLYGON)) |
+-------------------------------------------------------+-------------------------------------------------------------------------------------+
| POLYGON((35 135,35 135.5,35.3 135.5,35.5 135,35 135)) | POLYGON((35.05 135.3,35.05 135.8,35.349999999999994 135.8,35.55 135.3,35.05 135.3)) |
+-------------------------------------------------------+-------------------------------------------------------------------------------------+
1 row in set (0.000 sec) 地図上にプロットさせると、こんな感じ。青がもとのポリゴン、赤が移動後。

なお、MySQL Plugin の関数の戻り値にはGEOMETRY系の型を指定することができないため、結果の型はバイナリです(通常の関数に渡して処理する際にはそれでまったく問題ない)。DBeaverのような、型に応じてプロット処理をしてくれるツールではこのままだと表示してくれないため、以下のように結果を POLYGON型などにCASTします。
SET @g1=ST_GeomFromText('POLYGON((35 135, 35.5 135, 35.3 135.5, 35 135.5, 35 135))',6668);
SELECT CAST(@g1 AS POLYGON),
CAST(STX_Translate(@g1, 0.3, 0.05) AS POLYGON);
- LINESTRING型でも動作します。右(経度)に0.05, 上(緯度)方向に-1(つまり下)に移動させた例です
mysql> SET @g1=ST_GeomFromText('LINESTRING(35 135, 35.2 135.01, 35.3 134.8, 35.5 135.2)',6668);
mysql> SELECT ST_AsText(CAST(@g1 AS LINESTRING)),
-> ST_AsText(CAST(STX_Translate(@g1, 0.05, -0.1) AS LINESTRING));
+------------------------------------------------------+---------------------------------------------------------------------------------------+
| ST_AsText(CAST(@g1 AS LINESTRING)) | ST_AsText(CAST(STX_Translate(@g1, 0.05, -0.1) AS LINESTRING)) |
+------------------------------------------------------+---------------------------------------------------------------------------------------+
| LINESTRING(35 135,35.2 135.01,35.3 134.8,35.5 135.2) | LINESTRING(35.1 135.05,35.300000000000004 135.06,35.4 134.85000000000002,35.6 135.25) |
+------------------------------------------------------+---------------------------------------------------------------------------------------+
1 row in set (0.000 sec)
- もちろんデカルトでも動作します。
mysql> SET @g1=ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))');
mysql> SELECT ST_AsText(CAST(@g1 AS LINESTRING)),
-> ST_AsText(CAST(STX_Translate(@g1, 3, 5) AS LINESTRING));
+-------------------------------------+---------------------------------------------------------+
| ST_AsText(CAST(@g1 AS LINESTRING)) | ST_AsText(CAST(STX_Translate(@g1, 3, 5) AS LINESTRING)) |
+-------------------------------------+---------------------------------------------------------+
| LINESTRING(0 0,10 0,10 10,0 10,0 0) | LINESTRING(3 5,13 5,13 15,3 15,3 5) |
+-------------------------------------+---------------------------------------------------------+
1 row in set (0.000 sec)
- (例えばJGD2011やWGS84では)lat-lonの順序なのに、当関数の引数には lon-latの順で与えなければならないのが気持ち悪くて、オマケで STX_Translate_latlon() を作りました
mysql> SET @g1=ST_GeomFromText('POLYGON((35 135, 35.5 135, 35.3 135.5, 35 135.5, 35 135))',6668);
mysql> SELECT ST_AsText(CAST(@g1 AS POLYGON)),
-> ST_AsText(CAST(STX_Translate_latlon(@g1, 0.3, 0.05) AS POLYGON));
+-------------------------------------------------------+--------------------------------------------------------------------------------------+
| ST_AsText(CAST(@g1 AS POLYGON)) | ST_AsText(CAST(STX_Translate_latlon(@g1, 0.3, 0.05) AS POLYGON)) |
+-------------------------------------------------------+--------------------------------------------------------------------------------------+
| POLYGON((35 135,35 135.5,35.3 135.5,35.5 135,35 135)) | POLYGON((35.3 135.05,35.3 135.55,35.599999999999994 135.55,35.8 135.05,35.3 135.05)) |
+-------------------------------------------------------+--------------------------------------------------------------------------------------+
1 row in set (0.000 sec) プロットしてみると、第2引数の 0.3が緯度として扱われた移動をしていることがわかります。

開発秘話
この、「引数 X,Yの順序は、右、上!」という仕様に悩みました。測地系に応じた指定ができたほうが良いのではないか等、検討したのですが、他のツールとの互換性や慣例などを鑑み、ST_Translate()はそのままの仕様とすることにしました。かわりに ST_Translate_latlon()という関数をでっちあげることで、lat-lon順で使いたいという要求を満たしています。
この平行移動機能、GEOMETRYを構成する各POINTへのプラスマイナスの演算を行うだけなのですが、なんだか「地理情報データを加工した!」という気分になれて、なかなか気持ちの良いものです。