PLATEAUの３DモデルからBlenderで河口付近の川や海を削除する


# 動作確認済み環境
- Windows 11
- Blender 3.6.14


# 何をするのか
PLATEAUの３DモデルからBlenderで河口付近の川や海を削除します。
（以下画像の左から右へ）

[![Image from Gyazo](https://i.gyazo.com/0a42d16bd52f9d7a937879535b619556.jpg)](https://gyazo.com/0a42d16bd52f9d7a937879535b619556)



# 手順

Unityで、PLATEAU SDKを使って、3D都市モデルをFBX化し、
それをBlenderにインポートした状態から始めます。
（本件では福山市芦田川流域を例にします）

[![Image from Gyazo](https://i.gyazo.com/6dfdf7634a7ef4878fcfd139dcf6fe47.jpg)](https://gyazo.com/6dfdf7634a7ef4878fcfd139dcf6fe47)

<br>
単純に考えると海抜が低いところが、川か海だろうから、
Y座標が1.0以下の頂点を削除してもらうスクリプトをChatGPTに作ってもらいました。

```script.py
import bpy
import bmesh

# 現在のオブジェクトを取得
obj = bpy.context.active_object

# オブジェクトがメッシュであることを確認
if obj.type != 'MESH':
    raise TypeError("Active object is not a mesh")

# 編集モードに切り替え
bpy.ops.object.mode_set(mode='EDIT')

# BMeshの作成
bm = bmesh.from_edit_mesh(obj.data)

# Y座標が1.0以下の頂点を削除するためのリストを設定
verts_to_remove = [v for v in bm.verts if v.co.y <= 1.0]

# 取り出した頂点を削除
bmesh.ops.delete(bm, geom=verts_to_remove, context='VERTS')

# 編集モードの変更をBlenderに反映
bmesh.update_edit_mesh(obj.data)

# オブジェクトモードに戻す
bpy.ops.object.mode_set(mode='OBJECT')

```
<br>
このコードをBlenderで動かすには、<br>
Blender の以下画像部分の<br>
１の「スクリプト作成」をクリック<br>
２の場所に以下のコードを入れます。<br>

[![Image from Gyazo](https://i.gyazo.com/7f8abfbb854728559ac01e82a822b07b.png)](https://gyazo.com/7f8abfbb854728559ac01e82a822b07b)

そして、実行します。
[![Image from Gyazo](https://i.gyazo.com/0e421b6720a19ff62ac36f082e8cc96b.png)](https://gyazo.com/0e421b6720a19ff62ac36f082e8cc96b)

海や川以外に、一部低い陸地も削除されました。
川の方が高い場所があることを考慮に入れてませんでした。
[![Image from Gyazo](https://i.gyazo.com/37e411076afd307772f963fa735d8c7d.png)](https://gyazo.com/37e411076afd307772f963fa735d8c7d)


<br><br>
川より低い陸地問題を解決するには、
ある程度範囲をしぼって、
その範囲の中から、
Yが1以下の頂点を削除したらいいのではないか？と考え、
以下スクリプトをChatGPTに作ってもらいました。

```script.py
import bpy
import bmesh

# オブジェクトを編集モードに変更
bpy.ops.object.mode_set(mode='EDIT')

# BMeshの取得
mesh = bmesh.from_edit_mesh(bpy.context.object.data)

# 削除する頂点をリスト化
verts_to_delete = [vert for vert in mesh.verts if vert.select and vert.co.y <= 1]

# 頂点の削除
bmesh.ops.delete(mesh, geom=verts_to_delete, context='VERTS')

# メッシュの更新
bmesh.update_edit_mesh(bpy.context.object.data)

```

編集モードで、
削除したい範囲を選択して、

[![Image from Gyazo](https://i.gyazo.com/7a78bac89b6223f7f12420cc38e9310c.png)](https://gyazo.com/7a78bac89b6223f7f12420cc38e9310c)

先ほどののスクリププトを実行します。


お、いい感じに海と川が削除できました。

[![Image from Gyazo](https://i.gyazo.com/093fb4c7dd2e5d4979450974359810b1.png)](https://gyazo.com/093fb4c7dd2e5d4979450974359810b1)

あとは手動で微調整します。

<br><br>

ただ、これだとちょっと上流が難しいです。
それで、以下の方法をとりました。

[![Image from Gyazo](https://i.gyazo.com/2738475fdbe6ddeff8dc35e4f0114e62.jpg)](https://gyazo.com/2738475fdbe6ddeff8dc35e4f0114e62)

手動でだいたい高さのあたりをつけます。

編集モードにします。
[![Image from Gyazo](https://i.gyazo.com/de78619b371686ccee385b8b6833dd52.png)](https://gyazo.com/de78619b371686ccee385b8b6833dd52)

これだと、どこなのかよく分からないので、ここをクリックして、テクスチャを重ねます。
[![Image from Gyazo](https://i.gyazo.com/601a14b3a006838e7511e9b897839051.png)](https://gyazo.com/601a14b3a006838e7511e9b897839051)

[![Image from Gyazo](https://i.gyazo.com/06ce568d37c855f11706e9342fbce372.jpg)](https://gyazo.com/06ce568d37c855f11706e9342fbce372)

適当に川の部分や近くの陸の部分のYのサイズを測ります。

地図をクリックしたら下画像のように座標が現れます。
[![Image from Gyazo](https://i.gyazo.com/56a3e9272063456f92a3b79f1e2dbe2f.jpg)](https://gyazo.com/56a3e9272063456f92a3b79f1e2dbe2f)

いろいろ測ってみて、
Y座標が1.7以上2.7以下が川部分と思われます。

川部分を選択します。<br>
（実際はこんなに大雑把ではないです）
[![Image from Gyazo](https://i.gyazo.com/5d4d95559322a184c39114913c6d3b4a.jpg)](https://gyazo.com/5d4d95559322a184c39114913c6d3b4a)

何も現れませんが、ここクリックすると、
[![Image from Gyazo](https://i.gyazo.com/b745f9736f7e75ecf2f4ea4df29055e6.jpg)](https://gyazo.com/b745f9736f7e75ecf2f4ea4df29055e6)


選択されてます。
[![Image from Gyazo](https://i.gyazo.com/14a937239b559aa34c6616873781a6d0.png)](https://gyazo.com/14a937239b559aa34c6616873781a6d0)

<br>
以下ChatGPTに
選択した場所について、Y座標が1.7以上2.7以下のものを削除するスクリプトを作ってもらいました。



```script.py
import bpy
import bmesh

# オブジェクトを編集モードに変更
bpy.ops.object.mode_set(mode='EDIT')

# BMeshの取得
mesh = bmesh.from_edit_mesh(bpy.context.object.data)

# 削除する頂点をリスト化（Y座標が1.7以上2.7以下のもの）
verts_to_delete = [vert for vert in mesh.verts if vert.select and 1.7 <= vert.co.y <= 2.7]

# 頂点の削除
bmesh.ops.delete(mesh, geom=verts_to_delete, context='VERTS')

# メッシュの更新
bmesh.update_edit_mesh(bpy.context.object.data)

```


実行

[![Image from Gyazo](https://i.gyazo.com/b01b11fede105b5bc79eeab3db68881d.png)](https://gyazo.com/b01b11fede105b5bc79eeab3db68881d)



だいたい削除されました。

あとは、手動で削除します。

なんだ、結局手動？
と思うかもしれませんが、
ある程度あたりがつけられるので、私には楽ちんでした。

<br><br>

最終的にできたのがこれです。

[![Image from Gyazo](https://i.gyazo.com/92f685ad04f7437cc78e6f666eb8defc.jpg)](https://gyazo.com/92f685ad04f7437cc78e6f666eb8defc)

<br>
もっと細かくやればよかったと後悔してますが、<br>
とりあえずは以上です。