GIS初心者でも安心!Djangoにおけるgis.geos.GEOSGeometry.difference()のわかりやすい解説


このメソッドは、様々な場面で役立ちます。例えば、土地利用状況を分析する際に、建物のフットプリントジオメトリから道路のジオメトリを引いて、実際に利用可能な土地面積を計算することができます。

メソッドの構文

difference(other_geom)

ここで、other_geom は、引かれるジオメトリを表す GEOSGeometry オブジェクトです。

メソッドの戻り値

このメソッドは、新しい GEOSGeometry オブジェクトを返します。このオブジェクトは、引かれるジオメトリが重なっていた部分を除いた元のジオメトリを表します。


from django.contrib.gis.geos import GEOSGeometry

# 2つのジオメトリを作成
geom1 = GEOSGeometry('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))', srid=4326)
geom2 = GEOSGeometry('POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))', srid=4326)

# geom1 から geom2 を引く
difference = geom1.difference(geom2)

# 結果を表示
print(difference.wkt)

この例では、以下の結果が出力されます。

SRID=4326;POLYGON((0 0, 0 5, 5 5, 10 5, 10 0, 5 0, 0 0))

この結果は、geom1 から geom2 が重なっていた部分 (中央の正方形) が除かれたことを示しています。

  • 引かれるジオメトリが元のジオメトリよりも大きい場合は、空のジオメトリが返されます。
  • 引かれるジオメトリが元のジオメトリとまったく重なっていない場合は、元のジオメトリのコピーが返されます。
  • difference() メソッドは、引かれるジオメトリが元のジオメトリの一部と一致する場合のみ結果を返します。


土地の利用可能な面積を計算する

この例では、建物のフットプリントジオメトリから道路のジオメトリを引いて、実際に利用可能な土地面積を計算します。

from django.contrib.gis.geos import GEOSGeometry

# それぞれのジオメトリを作成
building_geom = GEOSGeometry('POLYGON((0 0, 100 0, 100 50, 0 50, 0 0))', srid=4326)
road_geom = GEOSGeometry('LINESTRING((20 0, 20 50))', srid=4326)

# 利用可能な土地面積を計算
available_land = building_geom.difference(road_geom)

# 結果の面積を出力
print(available_land.area)

このコードは、以下の結果を出力します。

5000.0

複数のジオメトリから共通部分を引く

この例では、複数のジオメトリから共通部分を引いて、残りの部分を計算します。

from django.contrib.gis.geos import GEOSGeometry

# それぞれのジオメトリを作成
geom1 = GEOSGeometry('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))', srid=4326)
geom2 = GEOSGeometry('POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))', srid=4326)
geom3 = GEOSGeometry('POLYGON((20 20, 30 20, 30 30, 20 30, 20 20))', srid=4326)

# すべてのジオメトリから共通部分を引く
difference = geom1.difference(geom2).difference(geom3)

# 結果を表示
print(difference.wkt)
SRID=4326;POLYGON((0 0, 0 5, 5 5, 10 5, 10 0, 5 0, 0 0))

この結果は、geom1geom2geom3 のすべてが重なっていた部分を除いた領域を示しています。

ジオメトリの一部を切り抜く

この例では、ジオメトリの一部を切り抜きます。

from django.contrib.gis.geos import GEOSGeometry

# ジオメトリを作成
geom = GEOSGeometry('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))', srid=4326)

# 切り抜きジオメトリを作成
cutout_geom = GEOSGeometry('POLYGON((5 5, 7.5 5, 7.5 7.5, 5 7.5, 5 5))', srid=4326)

# 切り抜きを実行
difference = geom.difference(cutout_geom)

# 結果を表示
print(difference.wkt)
SRID=4326;MULTIPOLYGON(
 ((0 0, 0 5, 5 5, 7.5 5, 7.5 7.5, 5 7.5, 5 10, 10 10, 10 5, 10 0, 0 0)),
 ((5 0, 5 5, 7.5 5, 7.5 0, 5 0))
)

この結果は、cutout_geom で指定された領域が geom から切り抜かれたことを示しています。

  • 引かれるジオメトリが複雑な形状の場合、処理時間が
  • ジオメトリの座標系 (srid) が一致していることを確認してください。異なる座標系の場合、正しく結果が得られない可能性があります。


以下に、いくつかの代替方法とその利点と欠点をご紹介します。

gis.geos.GEOSGeometry.symmetric_difference()

このメソッドは、2つのジオメトリの差と和を計算します。つまり、difference()union() の結果を組み合わせたものです。

利点:

  • 穴あきポリゴンなどの処理にも適しています。
  • 複雑なジオメトリの差を計算する場合に役立ちます。

欠点:

  • 結果がより複雑になる可能性があります。
  • difference() よりも処理時間がかかる場合があります。

カスタムジオメトリ演算

より複雑なジオメトリ演算が必要な場合は、カスタムジオメトリ演算を実装することができます。

  • 処理速度を最適化することができます。
  • 特定のニーズに合わせた処理を行うことができます。
  • デバッグが難しい場合があります。
  • プログラミングスキルが必要となります。

GISライブラリ

Shapely や GeoPandas などの他の GIS ライブラリを使用することもできます。これらのライブラリは、difference() メソッドを含む様々なジオメトリ演算を提供しています。

  • 豊富な機能を提供しています。
  • Django 以外の環境でも使用できます。
  • 学習曲線が大きいかもしれません。
  • Django の contrib.gis モジュールとの互換性がない場合があります。

代替方法を選択する際の考慮事項

  • 互換性
  • プログラミングスキル
  • 必要な処理速度
  • 処理するジオメトリの複雑さ

gis.geos.GEOSGeometry.difference() は、多くの場合で便利なメソッドですが、状況によっては代替方法の方が適切な場合があります。上記で紹介した代替方法を検討し、ニーズに合った方法を選択してください。