0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Blender 4.2で日本地図(四色問題)

Last updated at Posted at 2022-03-20

これなに

Blenderで日本地図の県ごとにオブジェクトを作り、4色に塗ってみます。

完成物

四色問題を解く

県ごとの色は、数理最適化を用いて四色問題を解いて求めます。
数理最適化については、「組合せ最適化を使おう」を参考にしてください。

最初、BlenderのPythonで実行したのですが、異常終了してしまったため、色の割り当て(変数assignの値)は下記のコードで別途求めました。

from mip import Model

from japanmap import adjacent, get_data

qpqo = get_data()
m = Model()  # 数理モデル
v = m.add_var_tensor((47, 4), "v", var_type="I")
m += v.sum(axis=1) == 1
for ipr in range(47):
    for ad in adjacent(ipr + 1, qpqo):
        if ad > ipr:
            m += v[ipr] + v[ad - 1] <= 1
m.optimize()
assign = (v.astype(float) * range(4)).sum(axis=1).astype(int).tolist()
print(assign)

数理最適化は、Python-MIPライブラリーを用いています。
どうも、BlenderとPython-MIPは相性が悪いようです。ちなみに、Blender2.83では動きましたが、Blender2.93以降は動きませんでした。

Python-MIPの使い方については下記を参考にしてください。

ちなみに、「Blenderで隣り合う面に異なる色を割当(四色問題)」の貪欲法で色を求めると長野県のあたりで5色目を使ってたので、定式化して解くことにしました。

やってみる

県の境界の座標や、県間の隣接関係は、japanmapというライブラリーを用います。
japanmapについては、「県別データの可視化」を参考にしてください。

Blender上で下記を実行すると、日本地図ができます。

import bpy
import numpy as np
from mathutils import Vector

from japanmap import get_data, pref_names, pref_points

colors = [
    (1, 0.1, 0.1, 1),
    (0.1, 0.2, 1, 1),
    (0.8, 0.8, 0, 1),
    (0, 0.8, 0.1, 1),
]
center = np.array([139.75, 35.68])
assign = [
    0, 2, 0, 2, 1, 0, 3, 0, 2, 1, 3, 2, 0, 2, 2, 1, 0, 3, 1, 0, 2, 3, 1, 0,
    1, 2, 0, 1, 3, 2, 0, 1, 2, 3, 0, 1, 0, 3, 0, 0, 2, 1, 1, 3, 2, 0, 3,
]

for i, color in enumerate(colors):
    mat = bpy.data.materials.new(name=f"M{i}")
    mat.use_nodes = True
    mat.node_tree.nodes["Principled BSDF"].inputs["Base Color"].default_value = color
pnts = pref_points(get_data())
for ipr in range(47):
    verts = [Vector([*pt, 0]) for pt in (pnts[ipr] - center).tolist()]
    mesh = bpy.data.meshes.new(name=pref_names[ipr + 1])
    mesh.from_pydata(verts, [], np.arange(len(verts))[None, :])
    obj = bpy.data.objects.new(mesh.name, mesh)
    obj.active_material = bpy.data.materials.get(f"M{assign[ipr]}")
    bpy.context.scene.collection.objects.link(obj)
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.mode_set(mode="EDIT")
    bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value": (0, 0, 0.2)})
    bpy.ops.transform.resize(value=(0.96, 0.96, 0.96))
    bpy.ops.object.mode_set(mode="OBJECT")

参考:BlenderでPythonを実行する方法

以上

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?