等高線やCTスキャンなどの断面図から3Dモデルを自作する方法【Blender2.9】

https://youtu.be/UmmwD0w4Xio
この動画の内容をスクリプトにしたものです。

```
import bpy #bpyというモジュールを使いますという宣言

obj = bpy.context.view_layer.objects.active #アクティブなオブジェクトをobjとする
obj_name = obj.name #objの名前をobj_nameとしてメモっておく
obj.name = "p_c" #objの名前をp_cに変更 (pre_curveの略)


bpy.data.objects['p_c'].select_set(True) #オブジェクト "p_c"を選択
obj = bpy.context.window.scene.objects['p_c'] #”p_c”という名前のオブジェクトをobjとする
bpy.context.view_layer.objects.active = obj #obj (="p_c")をアクティブにする

bpy.ops.object.modifier_apply(modifier="Subdivision") #サブディビジョンサーフェスを適用 (必要なら)

bpy.ops.object.mode_set(mode="EDIT") #編集モードに切り替え
bpy.ops.mesh.separate(type='LOOSE') #構造的に分離したパーツで分割
bpy.ops.object.mode_set(mode="OBJECT") #オブジェクトモードに切り替え

bpy.ops.object.convert(target="CURVE") #カーブに変換
bpy.context.object.data.use_stretch = True #カーブの設定のストレッチを有効にする
bpy.context.object.data.use_deform_bounds = True #カーブの設定の境界固定を有効にする

edge_obj=bpy.data.objects['edge'] #”edge”という名前のオブジェクトをedge_objとする
#(重要)edgeオブジェクトはX個の頂点を持つ棒状のオブジェクトです→
#→前もって用意しておく必要があります(手作業でも作れますが一番最後にスクリプトでの作り方を載せてあります)
bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする
edge_obj.select_set(True) #edge_objを選択する

bpy.ops.object.modifier_add(type='CURVE') #カーブモディファイアを追加
bpy.context.object.modifiers["Curve"].object = bpy.data.objects["p_c"]
#”p_c”という名前のカーブをカーブモディファイアに設定する
bpy.context.object.modifiers["Curve"].deform_axis = 'POS_Z' #変形軸をZ軸にする

#↑の処理を、p_cだけではなく、p_c.001、p_c.002、、にも同様に行っていく。
slice_n = 30 #階層の数を30とする (実際の階層数を超えていればなんでもOK)
#★★繰り返し処理Aはここから
for i in range(1,slice_n+1): #1から ↑で決めた階層数(slice_n)まで処理を繰り返す
curve_name = "p_c." + str(i).zfill(3) #p_c .001、p_c.002、、をcurve_nameとする
#zfill (3)は1を001、2を002、、にする関数
p_c_2 = bpy.data.objects.get(curve_name)
#curve_nameという名前のオブジェクトをp_c_2とする
#↓そんな名前のオブジェクトが存在するか確認する
if p_c_2 == None: #p_c .XXXが存在しなくなったら、
break #繰り返し処理を終了する

p_c_2 = bpy.context.window.scene.objects[curve_name]
bpy.context.view_layer.objects.active = p_c_2 #p_c_2をアクティブにする
bpy.data.objects[curve_name].select_set(True) #選択する
bpy.context.object.data.use_stretch = True #ストレッチを有効にする
bpy.context.object.data.use_deform_bounds = True #境界固定を有効にする

#★★★ここで一区切り★★★
for ob in bpy.context.scene.objects:
#全てのオブジェクトを非選択状態に設定する
ob.select_set(False)

#edge_obj =bpy.data.objects['edge'] “edge”という名前のオブジェクトをedge_objとする
bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする
edge_obj.select_set(True) #edge_objを選択する
bpy.ops.object.duplicate_move(OBJECT_OT_duplicate=None, TRANSFORM_OT_translate=None) #edgeを複製する (Shift+Dの操作)

bpy.context.object.modifiers["Curve"].object = bpy.data.objects[curve_name]
#カーブモディファイアを設定し 、カーブをcurve_name(p_c.XXXとか)を設定
bpy.context.object.modifiers["Curve"].deform_axis = 'POS_Z'
#変形軸をZ軸に設定

#★★繰り返し処理Aはここまで


edge_obj=bpy.data.objects['edge'] #edgeという名前のオブジェクトをedge_objとする
bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする
edge_obj.select_set(True) #edge_objを選択する
bpy.ops.object.modifier_apply(modifier="Curve") #カーブモディファイアを適用する

#↑の処理を、edgeだけではなく、edge.001、edge.002、、にも同様に行っていく。
#★★繰り返し処理Bはここから
for i in range(1,slice_n+1): #1から ↑で決めた階層数(slice_n)まで処理を繰り返す
edge_name = "edge." + str(i).zfill(3) #edge .001、edge.002、、をedge_nameとする
#zfill (3)は1を001、2を002、、にする関数
edge_2 = bpy.data.objects.get(edge_name)
#edge_nameという名前のオブジェクトをedge_2とする
#↓edge.XXXが存在するか確認する
if edge_2 == None:
break #存在しなかったら繰り返しを終了する
edge_2.select_set(True) #edge_2を選択する
bpy.context.view_layer.objects.active = edge_2 #edge_2をアクティブにする
bpy.ops.object.modifier_apply(modifier="Curve") #カーブモディファイアを適用
#★★繰り返し処理Bはここここまで


bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする
#ここまでの流れでedge ～edge.XXXはすでに全て選択されている
bpy.ops.object.join() # edge～edge.XXX を1つのオブジェクトに統合(Ctrl+jの操作)

edge_obj.name = obj_name #統合したオブジェクトにもとの名前 (obj_name※一番最初にメモってある)を返す


bpy.ops.object.mode_set(mode="EDIT") #編集モードに切り替え
bpy.ops.mesh.select_all(action='SELECT') #すべて選択
bpy.ops.mesh.remove_doubles() #距離でマージ
bpy.ops.mesh.bridge_edge_loops() #辺ループをブリッジ
bpy.ops.object.mode_set(mode="OBJECT") #オブジェクトモードに切り替え

#★★★ここで一区切り★★★

#使い終わったカーブを消す
for ob in bpy.context.scene.objects:
#全てのオブジェクトを非選択状態に設定する
ob.select_set(False)

curve_name = "p_c" #”p_c”をcurve_nameと呼ぶことにする
p_c_2 = bpy.data.objects.get(curve_name) #curve_nameを名前に持つオブジェクトをp_c_2とする
p_c_2.select_set(True) #p_c_2を選択
bpy.context.view_layer.objects.active = p_c_2 #p_c_2をアクティブにする
bpy.ops.object.delete(use_global=False, confirm=False) #p_c_2を削除する

#↑の処理を、p_cだけではなく、p_c.001、p_c.002、、にも同様に行っていく。
#★★繰り返し処理Cはここから
for i in range(1,slice_n+1): #1から ↑で決めた階層数(slice_n)まで処理を繰り返す
curve_name = "p_c." + str(i).zfill(3) #p_c .001、p_c.002、、をcurve_nameとする
#zfill (3)は1を001、2を002、、にする関数
p_c_2 = bpy.data.objects.get(curve_name)
#curve_nameという名前のオブジェクトをp_c_2とする
#↓そんな名前のオブジェクトが存在するか確認する
if p_c_2 == None:
break #もし存在しなかったら繰り返しを終了する
p_c_2.select_set(True) #p_c_2を選択する
bpy.context.view_layer.objects.active = p_c_2 #p_c_2をアクティブにする
bpy.ops.object.delete(use_global=False, confirm=False) #p_c_2を削除する
#★★繰り返し処理Cはここまで


#★★★ここで一区切り★★★

#次のためのedgeを作っておく 。(任意の頂点数を持つ棒をつくる。)

for ob in bpy.context.scene.objects:
#全てのオブジェクトを非選択状態に設定する
ob.select_set(False)

cut_num = 100 #細分化したい数
verts = [[0, 0, 0], [0, 0, 1]] #頂点0番 (0,0,0)と頂点1番(0,0,1)を定義
edges = [[0,1]] #頂点0番と頂点1番を結んだ辺をedgesとする

msh = bpy.data.meshes.new("cubemesh") #Meshデータの宣言
msh.from_pydata(verts, edges, []) #上で定義した頂点 、辺の情報でメッシュを作成
obj = bpy.data.objects.new("edge", msh) # メッシュデータでオブジェクトを作成
bpy.context.scene.collection.objects.link(obj) # シーンにオブジェクトを配置
bpy.data.objects['edge'].select_set(True) #オブジェクト "edge"を選択
bpy.context.view_layer.objects.active = obj #obj (="edge")をアクティブにする
bpy.ops.object.mode_set(mode="EDIT") #編集モードに切り替え

bpy.ops.mesh.subdivide(number_cuts=cut_num-1) #”edge”をcut_num-1箇所で細分化する(ctrl+E→細分化の操作)

bpy.ops.object.mode_set(mode="OBJECT") #オブジェクトモードに切り替え

```