Pyramid + GeoAlchemy2 + GeoFormAlchemy2 (2)

(承前)

ジオメトリの種類を変える

models.py の point を multipoint に変えてみる。

class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom_point = Column(Geometry('multipoint', 4612))

テーブルを作り直してアプリケーション再起動。 すると下図のように、OpenLayers インターフェイス上で 多点指定ができるようになった。

../../../_images/multipoint.png

linestring と multilinestring、 polygon と multipolygon も同様の関係になる。

さて汎用の geometry を指定した場合にどうなるか、だが、

geom = Column(Geometry('geometry', 4612))

point, linestring, polygon を自由に指定できる。

../../../_images/geometry.png

geometry は geometrycollection でも良いようだ。

geom = Column(Geometry('geometrycollection', 4612))

複数カラム

ひとつのテーブルに複数のジオメトリカラムを作成した場合にどうなるか、 見てみる。models.py を以下のように修正してテーブルを作り直す。

class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom_geometry = Column(Geometry('geometry', 4612))
    geom_point = Column(Geometry('multipoint', 4612))
    geom_line = Column(Geometry('multilinestring', 4612))
    geom_polygon = Column(Geometry('multipolygon', 4612))

アプリケーションを再起動すると下図のようになる。 注意するべきは、2段目、3段目に表示されるべきデータが 4段目に表示されているところである。

../../../_images/multicolumn.png

これは、GeoFormAlchemy の renderer が、OpenLayers 用に、 まったく同一の JavaScript コードを 4回出力しているからだと思われる。 OpenLayers インスタンスへの参照を保持する変数名を使い回すことになるため、 4個目のインスタンスだけが変数に格納され、 1-3個目のインスタンスは、メモリ上には存在するが JavaScpript コードからはアクセスできないようになる。 結果的に、すべての入力内容が 4個目のインスタンスに渡されることになる、 ということなのだろう。 ただ、上図では 1個目のインスタンスだけは正常に動作しているようで、 それが何故なのか、この理屈ではよく解らない。

ちなみにこのまま save しようとするとエラーが出る。4個目のカラムは multipolygon 用であり、point や linestring を格納しようとするとエラーが 出るのである。

GeoFormAlchemy のこの挙動をバグと捉えるかどうかは悩ましいところである。 何故なら、OpenGIS では基本的に、ひとつのテーブルに対して ジオメトリカラムはひとつであることを措定しているからだ。 GIS は地物を扱う。地物には様々な属性が附属しており、ジオメトリも 属性のひとつである。ひとつの地物が複数のジオメトリを持つことはありえない。 何故なら地物はひとまとまりの物理的実体であり、従ってひとまとまりの ジオメトリしか持ち得ないからである。

よって、そもそも上記の models.py のような、ジオメトリタイプごとに カラムを分けるようなテーブル設計は OpenGIS の流儀から外れている、 ということだ。複雑なジオメトリデータを格納する場合は geometrycollection を 使うべきである。

なお、私は昨日まで PostGIS 等を使用したことがなく、OpenGIS に関する 上記の記述も、ついさっき小一時間調べただけに過ぎない。 私の理解が間違っているかも知れないので直ちに真に受けてはいけない。

(続く)