Mesh to Part/ja
Partオブジェクトをメッシュに変換する
Part形状のような上位レベルのオブジェクトを メッシュのような単純なオブジェクトに変換するのは比較的簡単な処理です。Partオブジェクトの全ての面を三角形に変換して、結果の三角形(モザイク)をメッシュ構築に使用すればいいのです:
# ドキュメントには一つだけPartオブジェクトが入っているとしましょう import Mesh faces = [] shape = FreeCAD.ActiveDocument.ActiveObject.Shape triangles = shape.tessellate(1) # この数値がモザイクの精度を表します for tri in triangles[1]: face = [] for i in range(3): vindex = tri[i] face.append(triangles[0][vindex]) faces.append(face) m = Mesh.Mesh(faces) Mesh.show(m)
#let's assume our document contains one part object
import Mesh
faces = []
shape = FreeCAD.ActiveDocument.ActiveObject.Shape
triangles = shape.tessellate(1) # the number represents the precision of the tessellation)
for tri in triangles[1]:
face = []
for i in range(3):
vindex = tri[i]
face.append(triangles[0][vindex])
faces.append(face)
m = Mesh.Mesh(faces)
Mesh.show(m)
ときたまOpenCascadeが出力する特定の面の三角形が非常にいびつな場合があります。もし面に長方形パラメータ空間があり、穴やトリム曲線が無ければ独自にメッシュを作成することもできます:
import Mesh def makeMeshFromFace(u,v,face): (a,b,c,d)=face.ParameterRange pts=[] for j in range(v): for i in range(u): s=1.0/(u-1)*(i*b+(u-1-i)*a) t=1.0/(v-1)*(j*d+(v-1-j)*c) pts.append(face.valueAt(s,t)) mesh=Mesh.Mesh() for j in range(v-1): for i in range(u-1): mesh.addFacet(pts[u*j+i],pts[u*j+i+1],pts[u*(j+1)+i]) mesh.addFacet(pts[u*(j+1)+i],pts[u*j+i+1],pts[u*(j+1)+i+1]) return mesh
import Mesh
def makeMeshFromFace(u,v,face):
(a,b,c,d)=face.ParameterRange
pts=[]
for j in range(v):
for i in range(u):
s=1.0/(u-1)*(i*b+(u-1-i)*a)
t=1.0/(v-1)*(j*d+(v-1-j)*c)
pts.append(face.valueAt(s,t))
mesh=Mesh.Mesh()
for j in range(v-1):
for i in range(u-1):
mesh.addFacet(pts[u*j+i],pts[u*j+i+1],pts[u*(j+1)+i])
mesh.addFacet(pts[u*(j+1)+i],pts[u*j+i+1],pts[u*(j+1)+i+1])
return mesh
メッシュをPartオブジェクトに変換する
メッシュからPartオブジェクトへの変換はCADでの作業でも非常に重要な操作です。他の人たちからメッシュ形式の3Dデータを受け取ったり、他のアプリケーションからメッシュ形式の3Dデータを出力するというのはよくあることだからです。自由形状や大きな描画シーンを表現する場合にはメッシュは非常に実用的です。とても軽量だからです。しかしCADでの用途を考えた場合、一般的には三角形ではなく曲線で作成された面やソリッドなど、もっと多くの情報を保持できるより上位のオブジェクトの方が好まれます。
メッシュからこういった(FreeCADのパートモジュールで扱われる様な )上位オブジェクトへの変換は簡単な処理ではありません。メッシュは数千もの三角形で構成されている場合もありますし(例えば3Dスキャナーによって生成されている場合)、面と同じだけの数のソリッドを持った場合には処理がとんでもなく重くなることも考えられます。従って多くの場合、変換時に最適化を施す必要があるのです。
FreeCAD currently offers two methods to convert Meshes to Part objects. The first method is a simple, direct conversion, without any optimization:
import Mesh,Part
mesh = Mesh.createTorus()
shape = Part.Shape()
shape.makeShapeFromMesh(mesh.Topology,0.05) # the second arg is the tolerance for sewing
solid = Part.makeSolid(shape)
Part.show(solid)
The second method offers the possibility to consider mesh facets coplanar when the angle between them is under a certain value. This allows to build much simpler shapes: (let's assume our document contains one Mesh object)
# let's assume our document contains one Mesh object
import Mesh,Part,MeshPart
faces = []
mesh = App.ActiveDocument.ActiveObject.Mesh
segments = mesh.getPlanes(0.00001) # use rather strict tolerance here
for i in segments:
if len(i) > 0:
# a segment can have inner holes
wires = MeshPart.wireFromSegment(mesh, i)
# we assume that the exterior boundary is that one with the biggest bounding box
if len(wires) > 0:
ext=None
max_length=0
for i in wires:
if i.BoundBox.DiagonalLength > max_length:
max_length = i.BoundBox.DiagonalLength
ext = i
wires.remove(ext)
# all interior wires mark a hole and must reverse their orientation, otherwise Part.Face fails
for i in wires:
i.reverse()
# make sure that the exterior wires comes as first in the lsit
wires.insert(0, ext)
faces.append(Part.Face(wires))
shell=Part.Compound(faces)
Part.show(shell)
#solid = Part.Solid(Part.Shell(faces))
#Part.show(solid)