円形ポリゴン生成の定番ツール、BoundingCircle 関数をマスターしよう! Django で空間データを可視化する
from django.contrib.gis.db.models.functions import BoundingCircle
bounding_circle = BoundingCircle(expression, num_seg=48, **extra)
**extra
**: オプション引数として、データベースバックエンドに固有の引数を渡すことができます。num_seg
: 円形ポリゴンの分割数(PostGIS のみ)を指定します。デフォルトは 48 です。expression
: 対象となるジオメトリフィールドまたは式を指定します。
動作
BoundingCircle
関数は、入力ジオメトリの最小外接円を計算します。この円は、入力ジオメトリを完全に包含する最小の円形ポリゴンです。
以下の例では、City
モデルの location
フィールドに含まれる各都市の最小外接円を計算し、結果を bounding_circle
フィールドに格納します。
from django.contrib.gis.db.models.functions import BoundingCircle
City.objects.annotate(
bounding_circle=BoundingCircle('location')
)
BoundingCircle
関数は、PostGIS、SpatiaLite、MySQL Spatial などのデータベースバックエンドでサポートされています。
最小外接円の可視化
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.db.models.functions import BoundingCircle
from django.template.loader import get_template
from django.template import Context
cities = City.objects.annotate(
bounding_circle=BoundingCircle('location')
)
template = get_template('template.html')
context = {'cities': cities}
content = template.render(context)
print(content)
template.html
テンプレートには、以下のコードが含まれます。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>最小外接円</title>
<script src="https://leafletjs.com/"></script>
<link rel="stylesheet" href="https://leafletjs.com/">
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://www.mapbox.com/mts', {
attribution: '© <a href="https://mapbox.com/">Mapbox</a> © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors'
}).addTo(map);
{% for city in cities %}
var circle = L.circle([{{ city.location.y }}, {{ city.location.x }}], {{ city.bounding_circle.radius }}).addTo(map);
circle.bindPopup('{{ city.name }}');
{% endfor %}
</script>
</body>
</html>
このコードは、各都市の最小外接円を Leaflet マップに表示します。
この例では、BoundingCircle
関数を使用して、特定のポイントを含む都市を検索する方法を示します。
from django.contrib.gis.db.models.functions import BoundingCircle
from django.contrib.gis.geos import Point
point = Point(40.7128, -74.0060) # ニューヨーク市の座標
cities_in_nyc = City.objects.filter(
location__within=BoundingCircle(point)
)
このコードは、ニューヨーク市 (指定されたポイント) を含む円形ポリゴン内に位置するすべての都市を含む QuerySet
を返します。
上記の例は、BoundingCircle
関数の基本的な使用方法を示しています。この関数は、さまざまな方法で使用できます。
- ジオメトリの面積を計算する
- ジオメトリの重心を計算する
- 特定の距離以内に位置するジオメトリを検索する
これらのタスクを実行するには、BoundingCircle
関数を他の GIS 関数と組み合わせて使用します。
Geometry.envelope メソッド
Geometry
オブジェクトは、envelope
メソッドを提供します。このメソッドは、入力ジオメトリを含む最小の矩形を返します。矩形は、円形ポリゴンよりも効率的に計算できますが、円形ポリゴンよりも大きな面積になる可能性があります。
from django.contrib.gis.geos import Point, Polygon
point = Point(40.7128, -74.0060)
rectangle = point.envelope()
print(rectangle.area) # 矩形の面積を出力
カスタム関数
特定のニーズに合わない場合は、カスタム関数を作成することもできます。たとえば、特定の精度で円形ポリゴンを生成したい場合は、次のコードを使用できます。
from django.contrib.gis.geos import GEOSGeometry, Point
def bounding_circle_with_precision(point, precision):
# 円の半径を計算する
radius = point.distance(point.buffer(precision))
# 円形ポリゴンを生成する
circle = GEOSGeometry('Circle', point, radius)
return circle
point = Point(40.7128, -74.0060)
circle = bounding_circle_with_precision(point, 0.01)
print(circle.area) # 円形ポリゴンの面積を出力
上記以外にも、状況に応じて様々な代替方法が考えられます。
Geometry.union
メソッド: 2 つのジオメトリを結合します。Geometry.intersection
メソッド: 2 つのジオメトリの共通部分を計算します。Geometry.buffer
メソッド: ジオメトリを指定された距離だけ拡張します。
どの代替方法が適切かは、具体的なニーズによって異なります。以下の点を考慮する必要があります。
- メモリ使用量
- 処理速度
- 必要な精度