緯度経度の範囲判定ライブラリturfpyの範囲指定方法検証

# turfpy
turf.jsを再実装した地理空間データ分析を実行するための Python ライブラリ
[https://turfpy.readthedocs.io/en/latest/index.html](https://turfpy.readthedocs.io/en/latest/index.html)

※turf.js：Advanced geospatial analysis for browsers and Node.js
(ブラウザーと Node.js の高度な地理空間分析)

今回は緯度・経度で指定した範囲の内外を判断する処理に使用
範囲指定をあまり考えずに実行したら想定通りの判定をしなかったので
久しぶりに「qiita書こう！」とその内容をまとめました

# 前提条件
- 地図上で四角形で表示されている豊田スタジアムの競技場の範囲内か判定する
- 指定した範囲の倍の広さ（だいたい）でランダムに位置を2000ポイントを範囲内か判定する
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/ea1f452d-ef9b-6256-4734-ab6dd0571257.png">


# 確認方法（成功パターン）
## 緯度経度で範囲内か判定する関数準備
```python
from turfpy.measurement import boolean_point_in_polygon
from geojson import Point, Polygon, Feature

def point_check(latitude, longitude):
  point = Feature(geometry=Point((latitude, longitude)))
  polygon = Polygon(
      [
          [
            #   1：左上
              (35.08499763901068, 137.17026711732228),
            #   2：右上
              (35.085190785781094, 137.171211254785),
            #   3：右下
              (35.08409774461924, 137.1715170265769),
            #   4：左下
              (35.08391776454962, 137.17057825353157),
          ]
      ]
  )

  return boolean_point_in_polygon(point, polygon)

ion_map = folium.Map(location=[35.084558667377046, 137.17086793207127], zoom_start=20)
```

## 範囲表示

```python
import geojson as gj

map3 = folium.Map(location=[35.084558667377046, 137.17086793207127], zoom_start=20)
color = "yellow"
index = 1

# 指定ポイント表示
for y, x in polygon:
    folium.Marker(location=[y, x], icon=DivIcon(
    icon_size=(25, 25),
    icon_anchor=(0, 0),
    html='<div style="text-align: center; font-size: 11pt; color : black width: 25px; height: 25px; background: ' + str(color) + '; border:1px solid #666; border-radius: 50%; z-index:1000;">' + str(index) + '</div>'),
    popup=str(index)).add_to(map3)
    index += 1

# 図形表示用に緯度と経度を入れ替える
def swap(point):
    return point[1], point[0]

lng_lat = [list(map(swap, polygon))]

# 図形表示
area = gj.Polygon(lng_lat)
folium.GeoJson(area).add_to(map3)

map3
```
指定は左上を起点に四隅を順番に回るように指定
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/b6f36928-e767-8fce-bd01-0482ae3dd8bf.png">
いい感じに位置指定できている

### ランダムにポイント準備して判定した結果を地図表示
```python
import random

import folium
from folium.features import DivIcon
map = folium.Map(location=[35.084558667377046, 137.17086793207127], zoom_start=20)

for index in range(2000):
    y = random.uniform(35.08521712394161, 35.08388264644096)
    x = random.uniform(137.16996134553037, 137.17184425603844)
    output = point_check(y, x)
    match output:
        case False:
            color = "red"
        case True:
            color = "skyblue"

    folium.Marker(location=[y, x], icon=DivIcon(
        icon_size=(10, 10),
        icon_anchor=(0, 0),
        html='<div style="text-align: center; font-size: 11pt; color : black width: 10px; height: 10px; background: ' + str(color) + '; border:1px solid #666; border-radius: 50%; "></div>'),
        popup=str(index)).add_to(map)
map
```
## 判定結果
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/ba7f9b0a-698e-fcc2-a97f-d6a26ab594b8.png">

四角で範囲外、内を判定できている

# 範囲指定の順番を入れ替える
```python
  polygon = Polygon(
      [
          [
            #   1：左上
              (35.08499763901068, 137.17026711732228),
            #   2：右上
              (35.085190785781094, 137.171211254785),
            #   4：左下
              (35.08391776454962, 137.17057825353157),
            #   3：右下
              (35.08409774461924, 137.1715170265769),
          ]
      ]
```
## 範囲確認
「Z」を描くように範囲を指定
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/4390bae4-9892-782b-3a73-f9350f4ff314.png">
終点から視点をつなぎ
砂時計のように中央がしぼんだ形状になる

## 判定結果
図形でできた面の通り判定する
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/347e27ad-0f62-1825-080f-86cc6cd211df.png">

# おまけ（五角形→星形）
アメリカ国防総省本庁舎：ペンタゴン（五角形）の形で判定
## 範囲変更
```python
pentagon = [
            #   1：左上
              (38.87154327182928, -77.05665826702705),
            #   2：右上
              (38.87166063136013, -77.05554184655043),
            #   3：左下
              (38.870875785812466, -77.05499070226449),
            #   4：最下
              (38.870244969090606, -77.05581977401086),
            #   5：右下
              (38.87067040423856, -77.05686553496363),
          ]
print(pentagon)
```
## 範囲確認
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/5aa7a323-a091-b8d4-6a43-4cdbb9197dd0.png">

## 判定確認
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/f571228e-682b-d7b9-ebc7-2692f9737e92.png">

五角形で判定できている

# 星形に変更
```
pentagon = [
            #   1：左上
              (38.87154327182928, -77.05665826702705),
            #   3：左下
              (38.870875785812466, -77.05499070226449),
            #   5：右下
              (38.87067040423856, -77.05686553496363),
            #   2：右上
              (38.87166063136013, -77.05554184655043),
            #   4：最下
              (38.870244969090606, -77.05581977401086),
          ]
```
## 範囲確認
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/8052ec51-5fd3-e235-d907-1e555a86da09.png">

星形にきれいに描けている
よく見ると真ん中が抜けている

## 判定結果
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/b9df7ac4-d465-967b-df56-b694f5d4c36f.png">

図を描いたとおりに判定

# 星形にするには
指定ポイントを増やして
```python
pentagon = [
            #   1：左上
              (38.87154327182928, -77.05665826702705),
              (38.87128784974465, -77.05603043209587),
            #   2：右上
              (38.87166063136013, -77.05554184655043),
              (38.871133274341744, -77.05563029667685),
            #   3：左下
              (38.870875785812466, -77.05499070226449),
              (38.87084552538874, -77.05577996565037),
            #   4：最下
              (38.870244969090606, -77.05581977401086),
              (38.87078607298053, -77.05612817509899),
            #   5：右下
              (38.87067040423856, -77.05686553496363),
              (38.87105004129327, -77.05628089854136),
          ]
```
### 範囲確認
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/8a6530a8-8612-063b-a666-74e332c1b61c.png">

### 判定確認

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632401/7e7aeed4-4d06-ea87-c59c-53bd00f8f2f7.png">

成功！☆


# まとめ
- 指定したい範囲を移動してまわるように指定しないと意図しない判定になる
- 指定した順番でできる図形を作成することで判定範囲を確認できる

今回まとめる際に図形を表示させる等、
アウトプットすることで新しい操作も経験できたのでレベルアップできたと思います

またアウトプットしようと思いました。