DATE : 2007/12/11 (Tue)
※ これはインストールの仕方が悪かっただけなのかもしれません。ただ、長時間詰まってしまったので、ここにメモしておきます。
ST_Union( geometry set )という関数があります。これは、geometry で指定された幾何オブジェクトを結合する集約関数で、次のように使用します。ここで、幾何オブジェクトが格納されたテーブルは geometry_table で、幾何オブジェクトの列は the_geom と想定します。
SELECT ST_Union( the_geom ) FROM geometry_table;
上の例では、geometry_table テーブル内の the_geom 列に格納されている幾何オブジェクトが全て結合され、その結果、幾何オブジェクトひとつが返されます。
ところが、上の SQL を PostGIS 1.3.2 で実行すると、ST_Union( geometry )とマッチする関数はないというエラーが出てしまいました。
そこで、次のように ST_Union 関数の代わりに GeomUnion 関数を使用してみました。
SELECT GeomUnion( the_geom ) FROM geometry_table;
PostGIS の 1.3 未満では ST_Union の代わりに GeomUnion を使用していたので、昔のバージョンの関数ならば動くのではないかと踏んだのです。
そして、実際にこれはうまくいきました。ところが、PostGIS 1.3 以降は GeomUnion ではなく ST_Union 関数の使用が推奨されているので、このままではしっくりきません。将来のバージョンでは GeomUnion が削除されてしまう可能性もあります。
そこで、PostGIS 1.3 に付属する SQL 文を調べてみました。具体的には、「<PostgreSQL をインストールしたディレクトリ>\share\contrib\lwpostgis.sql」です。このファイルには、PostGIS の関数などが収められています。そのファイル内で、ST_Union や GeomUnion の集約関数の定義を探すと、次のように見つかりました。
-- Deprecation in 1.2.3 CREATE AGGREGATE GeomUnion ( sfunc = geom_accum, basetype = geometry, type = geometry[], finalfunc = ST_unite_garray ); -- Availability: 1.2.2 CREATE AGGREGATE ST_Union ( sfunc = ST_geom_accum, basetype = geometry, stype = geometry[], finalfunc = ST_unite_garray );
この定義を見ると、きちんと定義されているようです。しかも、定義の内容も GeomUnion と ST_Union とでまったく同じです。
そのため、上の ST_Union の定義を実行することで問題が解決しました。
(;^ω^)おそらくインストールの仕方が悪かったのだと思いますが、根本の原因はいまだに不明です。とりあえずの対処療法です。
DATE : 2007/10/26 (Fri)
空間情報ビューア、エディタの uDig は、PostGIS の geometry 型の列を認識して表示してくれます。
初めは、OpenGIS 仕様にのっとって、GEOMETRY_COLUMNS テーブルで指定されている列しか認識しないものと思っていたのですが、試しにビューを作って動的に幾何オブジェクトを生成した場合でも、uDig は認識して表示してくれました。
これで、uDig での表示用にビューを活用できることが分かりました。これまでは、わざわざ問い合わせからテーブルを生成していました。しかし、問い合わせからのテーブルの生成では、問い合わせ元のテーブルが更新されても生成されたテーブルは更新されません。そのため、表示用にビューが使えると、更新作業がいらず、楽になります。
DATE : 2007/10/10 (Wed)
国土地理院が提供する数値地図2500には、道路線の情報が含まれています。しかし、交差点や各道路のつなぎ目の情報は収録されていません。
そこで、次の SQL 文を実行すると、各道路線のつなぎ目が取得できます。ここで、道路情報は road テーブルの the_geom 列に格納されているとします。
SELECT DISTINCT ON ( ST_AsEWKB( location ) ) location FROM ( ( SELECT ST_StartPoint( the_geom ) AS location FROM road ) UNION ALL ( SELECT ST_EndPoint( the_geom ) AS location FROM road ) ) AS vertex_source;
(;^ω^)道路線の両端点を抽出して、重複する点を省いているだけです。
参考文献
- 数値地図2500を MapServer で表示させる 数値地図2500を PostGIS に格納するには、このページを参照してください。
DATE : 2007/09/25 (Tue)
DISTINCT 句を用いると、重複行を除去することができます。しかし、DISTINCT 句内で幾何オブジェクト(Geometry)を指定する場合には、幾何オブジェクトそのものを評価しているのか、幾何オブジェクトの境界(Boundary Box)を評価しているのか注意しなければいけません。
幾何オブジェクト同士の比較方法として「~=(幾何オブジェクトそのものの比較)」と「=(幾何オブジェクトの境界の比較)」の両方があります。DISTINCT 句や、その他の値同士を比較して出力行を変化させるような句では、「=(幾何オブジェクトの境界の比較)」で評価されます。つまり、特定の精度を越えた違いは全て同じと見なされてしまいます。
そのため、以下のような SQL 文を実行すると、重複していないにもかかわらず出力されない幾何オブジェクトが出てくる場合があります。この SQL 文は、点(POINT)オブジェクトの格納されたテーブル( point )から、重複する点オブジェクトを除いて出力することを想定しています。点オブジェクトは、location 列に格納されているものとします。
SELECT DISTINCT ON ( location ) location FROM point;
この問題は、幾何オブジェクトをバイナリに変換することで解決できます。バイナリに変換した上での SQL 文は、次の通りです。
SELECT DISTINCT ON ( ST_AsBinary( location ) ) location FROM point;
関連記事
参考文献
DATE : 2007/09/19 (Wed)
PostGIS では、幾何(geometry)オブジェクト同士の等しさを比較するための演算子が2種類用意されています。
- ~=
- 幾何オブジェクト同士が厳密に等しいかどうかを比較する。
- =
- 幾何オブジェクト同士の境界(boundary box)が等しいかどうかを比較する。
データベースに格納済の幾何オブジェクト同士を直接比較するには、なるべく「~=」演算子を使います。例えば、点(POINT)オブジェクトを考えてみます。点が密集しているところでは、それらの境界は同じとみなされることがあります。ある精度以上で密集していると、それらの境界はある程度で丸められてしまうようです。そのため、点が密集しているところで「=」演算子を使用すると、厳密には座標の異なる点オブジェクトまで等しい点オブジェクトと見なされることがあります。
ただし、データベースから特定の座標をテキスト情報(Well-Known Text など)で取り出して比較する場合には「=」を使う必要があります。テキストでの座標表現は特定の精度で丸められているため、データベース内のバイナリ形式で格納された座標と一致しません。そのため、データベースから取り出した情報から厳密な比較を行うには、テキスト情報ではなくバイナリ情報(Well-Known Binary など)で取り出す必要があります。