【GIS 開発者必見】Django contrib-gis の touches 関数を使いこなして、空間データ解析をレベルアップ!


"gis.gdal.OGRGeometry.touches()" は、Django の "django.contrib.gis" モジュールで提供される関数の一つであり、2つのジオメトリが接触しているかどうかを判定するために使用されます。

この関数は、空間関係演算の一つである "touches" を用いて、2つのジオメトリの境界線が接しているかどうかを調べます。 接触しているとは、2つのジオメトリの境界線が1点以上で共有されていることを意味します。

def touches(self, other):
    """
    Returns True if this geometry touches the other geometry.

    :param other: The other geometry to compare against.

    :rtype: bool
    """
    return self.intersects(other) & not self.within(other) & not other.within(self)

引数

  • other: 接触判定を行う対象となる別のジオメトリオブジェクト

戻り値

  • 2つのジオメトリが接触していない場合: False
  • 2つのジオメトリが接触している場合: True

動作原理

  1. intersects(): 2つのジオメトリが交差しているかどうかを判定します。
  2. within(): あるジオメトリが別のジオメトリ内にあるかどうかを判定します。

上記の2つの判定結果に基づいて、以下の条件を満たす場合のみ、2つのジオメトリが接触していると判断されます。

  • within(): False (双方がFalseでも可)
  • intersects(): True

使用例

from django.contrib.gis.gdal import OGRGeometry

polygon1 = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))')
polygon2 = OGRGeometry('POLYGON((5 0, 10 0, 10 5, 5 5))')

print(polygon1.touches(polygon2))  # True

上記の例では、polygon1polygon2 は境界線で1点共有しているため、touches() 関数は True を返します。

  • ジオメトリが空の場合、touches() 関数は False を返します。
  • ジオメトリの次元が異なる場合、touches() 関数は常に False を返します。
  • touches() 関数は、2つのジオメトリの境界線が接しているかどうかのみを判定します。 ジオメトリ同士が重なっているかどうかは判定しません。


不動産情報システムにおいて、隣接する土地を判定する機能を実装する際に役立ちます。

from django.contrib.gis.gdal import OGRGeometry

def is_neighboring_land(land1, land2):
    """
    2つの土地が隣接しているかどうかを判定します。

    :param land1: 1つ目の土地を表すジオメトリオブジェクト
    :param land2: 2つ目の土地を表すジオメトリオブジェクト
    
    :rtype: bool
    """
    return land1.touches(land2)

上記の例では、is_neighboring_land() 関数を作成し、2つの土地が隣接しているかどうかを判定します。 この関数は touches() 関数を使用して、2つの土地の境界線が接しているかどうかをチェックします。

道路網の分析

道路網の分析において、道路同士が接続しているかどうかを判定する際に役立ちます。

from django.contrib.gis.gdal import OGRGeometry

def is_connected_road(road1, road2):
    """
    2つの道路が接続しているかどうかを判定します。

    :param road1: 1つ目の道路を表すジオメトリオブジェクト
    :param road2: 2つ目の道路を表すジオメトリオブジェクト
    
    :rtype: bool
    """
    return road1.touches(road2)

上記の例では、is_connected_road() 関数を作成し、2つの道路が接続しているかどうかを判定します。 この関数は touches() 関数を使用して、2つの道路の境界線が接しているかどうかをチェックします。

災害時の避難経路の特定

災害発生時に、建物の被害状況と地形情報に基づいて、安全な避難経路を特定する際に役立ちます。

from django.contrib.gis.gdal import OGRGeometry

def find_safe_evacuation_route(building, terrain):
    """
    建物から安全な避難経路を見つけます。

    :param building: 避難対象となる建物を表すジオメトリオブジェクト
    :param terrain: 地形情報を含むジオメトリオブジェクト
    
    :rtype: list[OGRGeometry]
    """
    safe_routes = []
    for obstacle in terrain.geometries:
        if not building.touches(obstacle):
            safe_routes.append(obstacle)
    return safe_routes

上記の例では、find_safe_evacuation_route() 関数を作成し、建物から安全な避難経路を見つけます。 この関数は touches() 関数を使用して、建物と障害物が接触していないかどうかをチェックし、接触していない障害物を安全な避難経路として候補に挙げます。



intersects() 関数と within() 関数の組み合わせ

def touches_alternative(geometry1, geometry2):
    """
    "touches()" 関数の代替方法として、"intersects()" 関数と "within()" 関数を組み合わせて使用します。

    :param geometry1: 1つ目のジオメトリオブジェクト
    :param geometry2: 2つ目のジオメトリオブジェクト
    
    :rtype: bool
    """
    return geometry1.intersects(geometry2) & not geometry1.within(geometry2) & not geometry2.within(geometry1)

利点

  • 汎用性が高い
  • シンプルで分かりやすい

欠点

  • touches() 関数よりも若干処理速度が遅い可能性がある

ST_Touches() 関数 (PostGIS 使用時)

PostGIS を使用している場合は、ST_Touches() 関数を使用して2つのジオメトリが接触しているかどうかを判定することができます。

SELECT ST_Touches(geometry1, geometry2);

利点

  • 空間関係演算に関する豊富な関数群を利用できます
  • PostGIS に特化した高速な処理が可能です

欠点

  • PostGIS を使用していない場合は利用できません

カスタムアルゴリズム

具体的な状況に合わせて、独自のアルゴリズムを開発することも可能です。 例えば、2つのジオメトリの境界線の接点数を直接計算するなど、より詳細な判定を行うことができます。

利点

  • 高度な判定精度を実現できる可能性がある
  • 具体的な状況に最適化された判定が可能

欠点

  • コードの複雑度が高くなる可能性がある
  • 開発に時間がかかる

選択の指針

どの代替方法を選択するかは、以下の要素を考慮する必要があります。

  • 開発リソース
  • 使用しているデータベース
  • 必要な精度
  • 汎用性
  • 処理速度