BlenderとFreeCADを組み合わせてLoft機能(複数断面をつなぐ機能）を作成した

# モチベーション
会社で使用している有料CADのLoft機能が、イケなさすぎたので、BlenderとFreeCADを組み合わせて自作しました。FreeCADだけでもできるのだけれど、残念ながら形状やポイント数によって上手く繋がらなかった為、断面をつなぐ機能はBlenderにお任せしました。

# 環境作成(windows10)
- Anaconda3-5.2.0-Windows-x86_64をインストール
- FreeCADとBlenderをAnaconda環境へインストール

```
conda install -c conda-forge freecad
conda install -c kitsune.one python-blender 
```

# やりたいこと
座標(x,y,z)で定義された断面を繋いで、CAD形状を作りたい。
※CAEで解析するためには、CAD形状が便利なので。。。STLを上手くリメッシュして解析できればよいのになぁ

# やったこと
- 断面座標をpandas dataframeで定義（会社ではexcelから読み込んでます）

```sectiondata.py
import pandas as pd
df1 = pd.DataFrame([[0.0, -0.16, -1.61],
                     [0.0, -1.86, -1.26],
                     [0.0, -1.67, 0.77],
                     [0.0, -0.14, 1.29],
                     [0.0, 1.08, 1.58],
                     [0.0, -0.16, -1.61]],columns=["x","y","z"])

df2 = pd.DataFrame([[1.0, -0.76, -1.38],
                     [1.0, -1.77, -0.12],
                     [1.0, -1.1, 1.02],
                     [1.0, 0.14, 1.9],
                     [1.0, 0.9, 1.87],
                     [1.0, 1.31, 2.22],
                     [1.0, 0.99, -0.54],
                     [1.0, -0.17, -0.84],
                     [1.0, -0.76, -1.38]],columns=["x","y","z"])

lim=(-3,3)
df1.plot(x="y",y="z",xlim=lim,ylim=lim,linestyle='-',marker='.',title="section1")
df2.plot(x="y",y="z",xlim=lim,ylim=lim,linestyle='-',marker='.',title="section2")
```

【実行結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274127/d492c4c6-34c8-b1dd-65dc-6b80affe5ce9.png)



- blenderで上記座標点を作成し、辺ループのブリッジで3D形状を作成、blnder形式とstl形式でアウトプットする

```blender.py
import bpy
#立ち上げ時に存在するオブジェクト（立方体）を削除
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(use_global=True)

#前処理
n1,n2 = len(df1),len(df2)#座標点の数を取得
verts = pd.concat([df1,df2]).values.tolist()#blenderで認識できるように座標点をリスト化する
faces = [[i for i in range(n1)], [i for i in range(n1,n1+n2)]]#各々の面を定義するリストを作成

#Loftの作成
mesh = bpy.data.meshes.new(name="test")
mesh.from_pydata(verts,[],faces)#点と面を作成
mesh.update
obj = bpy.data.objects.new(name="test",object_data=mesh)
scene =bpy.context.scene
bpy.context.scene.objects.link(obj)
bpy.context.scene.objects.active = obj
bpy.ops.object.mode_set(mode = "EDIT")
bpy.ops.mesh.bridge_edge_loops()#辺ループのブリッジ->ここでLoft形状が作成される
bpy.ops.object.mode_set(mode = "OBJECT")

#output
bpy.ops.wm.save_mainfile(filepath="test.blend")#blenderfileを出力
bpy.ops.export_mesh.stl(filepath="test.stl")#STLを出力
```
【実行結果】
test.blenderとtest.stlが吐き出されます。下図の通り、見事にLoftしてくれます。Blenderはとっても優秀です！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274127/74961ff4-7648-39b9-ac2f-3973484c54df.png)



- 上記のstlをFreeCADで読み込み、stlからCAD形状を起こし、iges形式で吐き出す

```freecad.py
import FreeCAD as APP
import Mesh
import Part

freecad = APP.newDocument("model")

meshobj = freecad.addObject("Mesh::Feature","MyMesh")
meshobj.Mesh = Mesh.Mesh("test.stl")

shape = Part.Shape()
shape.makeShapeFromMesh(meshobj.Mesh.Topology,0.100000)
freecad.addObject("Part::Feature","test").Shape=Part.Solid(shape)
freecad.removeObject(meshobj.Name)
freecad.recompute()
freecad.saveAs("test.FCStd")
Part.export([freecad.Objects[0]],"test.iges")
```
【実行結果】
test.FCStdとtest.igesが吐き出されます。CADのSolidとなりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274127/aa784522-4b0d-878d-0c99-1b8b6995cfd0.png)

# ソースコード
下記サイトのLoft.ipynbにあります。
https://github.com/myao9494/Loft_feature_python

# ひとりごと
- 計算結果を3Dプリンタで出力したりも出来るようになります
- 地図データの等高線をCAD化したりするときも助かるはず（富士山をCAD化など）
- 3Dスキャナの結果をCAD化してCAEに掛けることも出来るようになるはず（リバースエンジニアリング）

ポイントクラウドをCAD化する有料ソフト等を使えれば、苦労しなくても良いのかも。。。良いのがあれば、教えてください。
（まぁ、良いものでも、簡単に買って貰えない会社なんですけどね。。。でもおかげ様で、OpenSourceにドンドン詳しくなっていく）