Django で GeoJSON データを操作する: gis.db.models.functions.SymDifference 関数の詳細解説
gis.db.models.functions.SymDifference
関数は、2つのジオメトリの対称差を求めるための関数です。対称差とは、2つのジオメトリを重ね合わせた部分を除いた領域のことを指します。
構文
from django.contrib.gis.db.models.functions import SymDifference
symdiff = SymDifference(geom1, geom2)
geom1
とgeom2
は、いずれもdjango.contrib.gis.db.models.fields.GeometryField
型のフィールドまたはジオメトリオブジェクトである必要があります。
戻り値
- 2つのジオメトリの対称差を表す
django.contrib.gis.geos.Geometry
オブジェクトが返されます。
例
from django.contrib.gis.geos import GEOSGeometry
# 2つのジオメトリを作成
geom1 = GEOSGeometry('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))')
geom2 = GEOSGeometry('POLYGON((5 0, 15 0, 15 10, 5 10, 5 0))')
# 対称差を求める
symdiff = SymDifference(geom1, geom2)
# 結果を表示
print(symdiff.wkt)
この例では、以下の結果が出力されます。
POLYGON((0 0, 10 0, 15 0, 15 10, 10 10, 5 10, 5 5, 0 5, 0 0))
- 2つのジオメトリが完全に重なる場合は、その結果として最初のジオメトリが返されます。
- 2つのジオメトリが重ならない場合は、その結果として空のジオメトリが返されます。
SymDifference
関数は、PostGIS 2.0以降のデータベースでのみ使用できます。
- 2つの建物の建蔽面積を比較する
- 2つの湖の面積の差を計算する
- 2つの土地の所有権の境界線を比較する
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.db.models.functions import Area
# 2つの土地の所有権の境界線を作成
land1_boundary = GEOSGeometry('POLYGON((0 0, 100 0, 100 50, 0 50, 0 0))')
land2_boundary = GEOSGeometry('POLYGON((50 0, 150 0, 150 60, 50 60, 50 0))')
# 土地の面積を計算する
land1_area = Area(land1_boundary)
land2_area = Area(land2_boundary)
# 対称差を求める
symdiff = SymDifference(land1_boundary, land2_boundary)
# 結果を表示
print(f"Land 1 area: {land1_area.m**2}")
print(f"Land 2 area: {land2_area.m**2}")
print(f"Symmetric difference area: {symdiff.area.m**2}")
Land 1 area: 2500.0
Land 2 area: 3000.0
Symmetric difference area: 1000.0
例 2:2つの湖の面積の差を計算する
この例では、2つの湖の面積を計算し、その差を求めます。
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.db.models.functions import Area
# 2つの湖の形状を作成
lake1_shape = GEOSGeometry('POLYGON((50 40, 60 40, 60 50, 50 50, 50 40))')
lake2_shape = GEOSGeometry('POLYGON((40 30, 70 30, 70 40, 40 40, 40 30))')
# 湖の面積を計算する
lake1_area = Area(lake1_shape)
lake2_area = Area(lake2_shape)
# 面積差を求める
area_diff = lake1_area - lake2_area
# 結果を表示
print(f"Lake 1 area: {lake1_area.m**2}")
print(f"Lake 2 area: {lake2_area.m**2}")
print(f"Area difference: {area_diff.m**2}")
Lake 1 area: 100.0
Lake 2 area: 140.0
Area difference: -40.0
例 3:2つの建物の建蔽面積を比較する
この例では、2つの建物の建蔽面積を比較します。
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.db.models.functions import Area
# 2つの建物の建蔽面積を作成
building1_footprint = GEOSGeometry('POLYGON((0 0, 10 0, 10 20, 0 20, 0 0))')
building2_footprint = GEOSGeometry('POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))')
# 建蔽面積を計算する
building1_area = Area(building1_footprint)
building2_area = Area(building2_footprint)
# 対称差を求める
symdiff = SymDifference(building1_footprint, building2_footprint)
# 結果を表示
print(f"Building 1 footprint area: {building1_area.m**2}")
print(f"Building 2 footprint area: {building2_area.m**2}")
print(f"Symmetric difference area: {symdiff.area.m**2}")
Building 1 footprint area: 200.0
ST_Difference 関数と ST_Union 関数の組み合わせ
PostGIS 2.0以降のデータベースを使用している場合は、ST_Difference
関数と ST_Union
関数を組み合わせて、SymDifference
関数と同じ結果を得ることができます。
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.db.models.functions import Difference, Union
# 2つのジオメトリを作成
geom1 = GEOSGeometry('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))')
geom2 = GEOSGeometry('POLYGON((5 0, 15 0, 15 10, 5 10, 5 0))')
# 対称差を求める
symdiff1 = Difference(geom1, Union(geom1, geom2))
symdiff2 = Difference(Union(geom1, geom2), geom2)
# 結果を表示
print(symdiff1.wkt)
print(symdiff2.wkt)
POLYGON((0 0, 10 0, 15 0, 15 10, 10 10, 5 10, 5 5, 0 5, 0 0))
POLYGON((0 0, 10 0, 15 0, 15 10, 10 10, 5 10, 5 5, 0 5, 0 0))
GEOSGeometry メソッドの使用
GEOSGeometry
オブジェクトには、difference()
メソッドと union()
メソッドが用意されており、これらのメソッドを使用して SymDifference
関数と同じ結果を得ることができます。
from django.contrib.gis.geos import GEOSGeometry
# 2つのジオメトリを作成
geom1 = GEOSGeometry('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))')
geom2 = GEOSGeometry('POLYGON((5 0, 15 0, 15 10, 5 10, 5 0))')
# 対称差を求める
symdiff1 = geom1.difference(geom1.union(geom2))
symdiff2 = geom1.union(geom2).difference(geom2)
# 結果を表示
print(symdiff1.wkt)
print(symdiff2.wkt)
POLYGON((0 0, 10 0, 15 0, 15 10, 10 10, 5 10, 5 5, 0 5, 0 0))
POLYGON((0 0, 10 0, 15 0, 15 10, 10 10, 5 10, 5 5, 0 5, 0 0))
カスタム SQL クエリ
PostGIS 2.0以降のデータベースを使用している場合は、カスタム SQL クエリを使用して SymDifference
関数と同じ結果を得ることができます。
SELECT ST_SymDifference(geom1, geom2) AS symdiff
FROM django_gis_geographyfield AS geom1, django_gis_geographyfield AS geom2
WHERE geom1.id = 1 AND geom2.id = 2;
このクエリは、geom1
と geom2
という名前のジオメトリフィールドを持つ 2 つのテーブルからデータを抽出し、ST_SymDifference
関数を使用して対称差を求めます。
最適な方法の選択
上記の代替方法のうち、最適な方法は、使用するデータベースの種類と、処理するジオメトリの複雑さによって異なります。
- より単純なジオメトリを処理する場合は、
- PostGIS 2.0以降のデータベースを使用している場合は、
ST_Difference
関数とST_Union
関数の組み合わせが最も効率的な方法です。