Mesh to Part/ja: Difference between revisions
No edit summary |
No edit summary |
||
(9 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
<languages/> |
<languages/> |
||
{{TOCright}} |
|||
<div class="mw-translate-fuzzy"> |
|||
== Partオブジェクトをメッシュに変換する == |
== Partオブジェクトをメッシュに変換する == |
||
</div> |
|||
<div class="mw-translate-fuzzy"> |
|||
[[Part |
[[Part Workbench/ja|Part形状]]のような上位レベルのオブジェクトを [[Mesh Workbench/ja|メッシュ]]のような単純なオブジェクトに変換するのは比較的簡単な処理です。Partオブジェクトの全ての面を三角形に変換して、結果の三角形(モザイク)をメッシュ構築に使用すればいいのです: |
||
# ドキュメントには一つだけPartオブジェクトが入っているとしましょう |
# ドキュメントには一つだけPartオブジェクトが入っているとしましょう |
||
# この数値がモザイクの精度を表します |
# この数値がモザイクの精度を表します |
||
</div> |
|||
{{Code|code= |
{{Code|code= |
||
#let's assume our document contains one part object |
|||
import Mesh |
import Mesh |
||
obj = FreeCADGui.Selection.getSelection()[0] # a Part object must be preselected |
|||
shp = obj.Shape |
|||
faces = [] |
faces = [] |
||
shape = FreeCAD.ActiveDocument.ActiveObject.Shape |
|||
triangles = |
triangles = shp.tessellate(1) # the number represents the precision of the tessellation |
||
for tri in triangles[1]: |
for tri in triangles[1]: |
||
face = [] |
face = [] |
||
for i in |
for i in tri: |
||
face.append(triangles[0][i]) |
|||
face.append(triangles[0][vindex]) |
|||
faces.append(face) |
faces.append(face) |
||
m = Mesh.Mesh(faces) |
m = Mesh.Mesh(faces) |
||
Mesh.show(m) |
Mesh.show(m) |
||
}} |
}} |
||
ときたまOpenCascadeが出力する特定の面の三角形が非常にいびつな場合があります。もし面に長方形パラメータ空間があり、穴やトリム曲線が無ければ独自にメッシュを作成することもできます: |
|||
Alternative example: |
|||
{{Code|code= |
{{Code|code= |
||
import Mesh |
import Mesh |
||
import MeshPart |
|||
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)) |
|||
obj = FreeCADGui.Selection.getSelection()[0] # a Part object must be preselected |
|||
⚫ | |||
shp = obj.Shape |
|||
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 |
|||
mesh.Mesh = MeshPart.meshFromShape( |
|||
Shape=shp, |
|||
LinearDeflection=0.01, |
|||
AngularDeflection=0.025, |
|||
Relative=False) |
|||
}} |
}} |
||
<div class="mw-translate-fuzzy"> |
|||
== メッシュをPartオブジェクトに変換する == |
== メッシュをPartオブジェクトに変換する == |
||
</div> |
|||
<div class="mw-translate-fuzzy"> |
|||
メッシュからPartオブジェクトへの変換はCADでの作業でも非常に重要な操作です。他の人たちからメッシュ形式の3Dデータを受け取ったり、他のアプリケーションからメッシュ形式の3Dデータを出力するというのはよくあることだからです。自由形状や大きな描画シーンを表現する場合にはメッシュは非常に実用的です。とても軽量だからです。しかしCADでの用途を考えた場合、一般的には三角形ではなく曲線で作成された面やソリッドなど、もっと多くの情報を保持できるより上位のオブジェクトの方が好まれます。 |
メッシュからPartオブジェクトへの変換はCADでの作業でも非常に重要な操作です。他の人たちからメッシュ形式の3Dデータを受け取ったり、他のアプリケーションからメッシュ形式の3Dデータを出力するというのはよくあることだからです。自由形状や大きな描画シーンを表現する場合にはメッシュは非常に実用的です。とても軽量だからです。しかしCADでの用途を考えた場合、一般的には三角形ではなく曲線で作成された面やソリッドなど、もっと多くの情報を保持できるより上位のオブジェクトの方が好まれます。 |
||
</div> |
|||
<div class="mw-translate-fuzzy"> |
|||
メッシュからこういった(FreeCADの[[Part Module/jp|パートモジュール]]で扱われる様な )上位オブジェクトへの変換は簡単な処理ではありません。メッシュは数千もの三角形で構成されている場合もありますし(例えば3Dスキャナーによって生成されている場合)、面と同じだけの数のソリッドを持った場合には処理がとんでもなく重くなることも考えられます。従って多くの場合、変換時に最適化を施す必要があるのです。 |
メッシュからこういった(FreeCADの[[Part Module/jp|パートモジュール]]で扱われる様な )上位オブジェクトへの変換は簡単な処理ではありません。メッシュは数千もの三角形で構成されている場合もありますし(例えば3Dスキャナーによって生成されている場合)、面と同じだけの数のソリッドを持った場合には処理がとんでもなく重くなることも考えられます。従って多くの場合、変換時に最適化を施す必要があるのです。 |
||
</div> |
|||
<div class="mw-translate-fuzzy"> |
|||
FreeCADでは現在、メッシュをPartオブジェクトに変換する二つのメソッドが用意されています。一つ目は単純なもので何の最適化も施さずに直接変換を行います: |
FreeCADでは現在、メッシュをPartオブジェクトに変換する二つのメソッドが用意されています。一つ目は単純なもので何の最適化も施さずに直接変換を行います: |
||
# 二つ目の引数は縫い合わせの許容誤差です |
# 二つ目の引数は縫い合わせの許容誤差です |
||
</div> |
|||
{{Code|code= |
{{Code|code= |
||
import Mesh |
import Mesh |
||
import Part |
|||
mesh = Mesh.createTorus() |
mesh = Mesh.createTorus() |
||
shape = Part.Shape() |
shape = Part.Shape() |
||
shape.makeShapeFromMesh(mesh.Topology,0.05) # the second arg is the tolerance for sewing |
shape.makeShapeFromMesh(mesh.Topology, 0.05) # the second arg is the tolerance for sewing |
||
solid = Part.makeSolid(shape) |
solid = Part.makeSolid(shape) |
||
Part.show(solid) |
Part.show(solid) |
||
}} |
}} |
||
<div class="mw-translate-fuzzy"> |
|||
二つ目のメソッドではメッシュの二つのファセットが作る角度が特定の値を下回る場合にその二つを同一面とみなします。これによってより単純な形状が作成できるのです: |
二つ目のメソッドではメッシュの二つのファセットが作る角度が特定の値を下回る場合にその二つを同一面とみなします。これによってより単純な形状が作成できるのです: |
||
Line 90: | Line 110: | ||
#solid = Part.Solid(Part.Shell(faces)) |
#solid = Part.Solid(Part.Shell(faces)) |
||
#Part.show(solid) |
#Part.show(solid) |
||
</div> |
|||
{{Code|code= |
{{Code|code= |
||
import Mesh |
|||
# let's assume our document contains one Mesh object |
|||
import |
import Part |
||
import MeshPart |
|||
obj = FreeCADGui.Selection.getSelection()[0] # a Mesh object must be preselected |
|||
⚫ | |||
⚫ | |||
faces = [] |
faces = [] |
||
⚫ | |||
⚫ | |||
for i in segments: |
for i in segments: |
||
if len(i) > 0: |
if len(i) > 0: |
||
# a segment can have inner holes |
# a segment can have inner holes |
||
wires = MeshPart.wireFromSegment(mesh, i) |
wires = MeshPart.wireFromSegment(mesh, i) |
||
# we assume that the exterior boundary is that one with the biggest bounding box |
# we assume that the exterior boundary is that one with the biggest bounding box |
||
if len(wires) > 0: |
if len(wires) > 0: |
||
ext=None |
ext = None |
||
max_length=0 |
max_length=0 |
||
for i in wires: |
for i in wires: |
||
if i.BoundBox.DiagonalLength > max_length: |
if i.BoundBox.DiagonalLength > max_length: |
||
max_length = i.BoundBox.DiagonalLength |
max_length = i.BoundBox.DiagonalLength |
||
ext = i |
ext = i |
||
wires.remove(ext) |
wires.remove(ext) |
||
# all interior wires mark a hole and must reverse their orientation, otherwise Part.Face fails |
# all interior wires mark a hole and must reverse their orientation, otherwise Part.Face fails |
||
for i in wires: |
for i in wires: |
||
i.reverse() |
i.reverse() |
||
# make sure that the exterior wires comes as first in the |
# make sure that the exterior wires comes as first in the list |
||
wires.insert(0, ext) |
wires.insert(0, ext) |
||
faces.append(Part.Face(wires)) |
faces.append(Part.Face(wires)) |
||
shell=Part.Compound(faces) |
|||
⚫ | |||
⚫ | |||
#Part.show(solid) |
|||
⚫ | |||
⚫ | |||
}} |
}} |
||
{{docnav|Topological data scripting|Scenegraph}} |
|||
⚫ | |||
{{Powerdocnavi{{#translation:}}}} |
|||
⚫ | |||
⚫ | |||
⚫ | |||
{{Mesh Tools navi{{#translation:}}}} |
Latest revision as of 09:35, 6 November 2021
Partオブジェクトをメッシュに変換する
Part形状のような上位レベルのオブジェクトを メッシュのような単純なオブジェクトに変換するのは比較的簡単な処理です。Partオブジェクトの全ての面を三角形に変換して、結果の三角形(モザイク)をメッシュ構築に使用すればいいのです:
# ドキュメントには一つだけPartオブジェクトが入っているとしましょう # この数値がモザイクの精度を表します
import Mesh
obj = FreeCADGui.Selection.getSelection()[0] # a Part object must be preselected
shp = obj.Shape
faces = []
triangles = shp.tessellate(1) # the number represents the precision of the tessellation
for tri in triangles[1]:
face = []
for i in tri:
face.append(triangles[0][i])
faces.append(face)
m = Mesh.Mesh(faces)
Mesh.show(m)
Alternative example:
import Mesh
import MeshPart
obj = FreeCADGui.Selection.getSelection()[0] # a Part object must be preselected
shp = obj.Shape
mesh = FreeCAD.ActiveDocument.addObject("Mesh::Feature", "Mesh")
mesh.Mesh = MeshPart.meshFromShape(
Shape=shp,
LinearDeflection=0.01,
AngularDeflection=0.025,
Relative=False)
メッシュをPartオブジェクトに変換する
メッシュからPartオブジェクトへの変換はCADでの作業でも非常に重要な操作です。他の人たちからメッシュ形式の3Dデータを受け取ったり、他のアプリケーションからメッシュ形式の3Dデータを出力するというのはよくあることだからです。自由形状や大きな描画シーンを表現する場合にはメッシュは非常に実用的です。とても軽量だからです。しかしCADでの用途を考えた場合、一般的には三角形ではなく曲線で作成された面やソリッドなど、もっと多くの情報を保持できるより上位のオブジェクトの方が好まれます。
メッシュからこういった(FreeCADのパートモジュールで扱われる様な )上位オブジェクトへの変換は簡単な処理ではありません。メッシュは数千もの三角形で構成されている場合もありますし(例えば3Dスキャナーによって生成されている場合)、面と同じだけの数のソリッドを持った場合には処理がとんでもなく重くなることも考えられます。従って多くの場合、変換時に最適化を施す必要があるのです。
FreeCADでは現在、メッシュをPartオブジェクトに変換する二つのメソッドが用意されています。一つ目は単純なもので何の最適化も施さずに直接変換を行います:
# 二つ目の引数は縫い合わせの許容誤差です
import Mesh
import 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)
二つ目のメソッドではメッシュの二つのファセットが作る角度が特定の値を下回る場合にその二つを同一面とみなします。これによってより単純な形状が作成できるのです:
# ドキュメントには一つだけMeshオブジェクトが入っているとしましょう # ここではより厳しい許容誤差を使用します for i in segments: if len(i) > 0: # 線分は内部に穴を持つことができます wires = MeshPart.wireFromSegment(mesh, i) # 外部境界が最大のバウンディングボックスを持つものであると仮定します 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) # 内部のワイヤーが全てマークされ、向きが反転されなければなりません。さもなければPart.Faceが失敗します for i in wires: i.reverse() # 外部のワイヤーがリストの先頭になっていることを確認してください 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)
import Mesh
import Part
import MeshPart
obj = FreeCADGui.Selection.getSelection()[0] # a Mesh object must be preselected
mesh = obj.Mesh
segments = mesh.getPlanarSegments(0.00001) # use rather strict tolerance here
faces = []
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 list
wires.insert(0, ext)
faces.append(Part.Face(wires))
solid = Part.Solid(Part.Shell(faces))
Part.show(solid)
Power user documentation
- FreeCAD scripting: Python, Introduction to Python, Python scripting tutorial, FreeCAD Scripting Basics
- Modules: Builtin modules, Units, Quantity
- Workbenches: Workbench creation, Gui Commands, Commands, Installing more workbenches
- Meshes and Parts: Mesh Scripting, Topological data scripting, Mesh to Part, PythonOCC
- Parametric objects: Scripted objects, Viewproviders (Custom icon in tree view)
- Scenegraph: Coin (Inventor) scenegraph, Pivy
- Graphical interface: Interface creation, Interface creation completely in Python (1, 2, 3, 4, 5), PySide, PySide examples beginner, intermediate, advanced
- Macros: Macros, How to install macros
- Embedding: Embedding FreeCAD, Embedding FreeCADGui
- Other: Expressions, Code snippets, Line drawing function, FreeCAD vector math library (deprecated)
- Hubs: User hub, Power users hub, Developer hub
Mesh
- Miscellaneous: Import mesh, Export mesh, Create mesh from shape, Regular solid, Unwrap Mesh, Unwrap Face
- Modifying: Harmonize normals, Flip normals, Fill holes, Close hole, Add triangle, Remove components, Remove components by hand, Smooth, Refinement, Decimation, Scale
- Boolean: Union, Intersection, Difference
- Cutting: Cut mesh, Trim mesh, Trim mesh with a plane, Create section from mesh and plane, Cross-sections
- Components and segments: Merge, Split by components, Create mesh segments, Create mesh segments from best-fit surfaces