我的最终目标如下:
我有一个巨大的点数据集,表示一个部件将如何逐层3D打印。我需要通过这些点创建一条直线并沿着这条直线挤出一个圆(所以重建部件,因为它将在以后打印)。
我最初尝试做一个样条曲线,但是这会尝试创建一条平滑线并且根本不遵循这些点。我尝试更改minDeg和maxDeg选项,但这仍然没有足够的帮助来创建我需要的实际曲线。
See this result for the spline
See here the actual path (the above spline is one of the infill parts)
所以我一次尝试在两个点之间创建一个样条线,然后在创建一条线时将它们全部加在一起。这看起来很有希望,因为现在我确实得到了实际的尖角和线条通过精确点。但是,现在当我尝试沿着它挤出时,挤出型材的法线不会随着钢丝的角度而变化。
This is what happens with the last thing I tried
我在这个问题上度过了最后4天,尝试了许多论坛和问题,但在pythonocc(opencascade)的世界中感到完全迷失了。
我的代码如下:
from __future__ import print_function
from OCC.gp import gp_Pnt, gp_Ax2, gp_Dir, gp_Circ
from OCC.GeomAPI import GeomAPI_PointsToBSpline
from OCC.TColgp import TColgp_Array1OfPnt
from OCC.BRepBuilderAPI import BRepBuilderAPI_MakeEdge,
BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeFace
from OCC.BRepOffsetAPI import BRepOffsetAPI_MakePipe
from OCC.Display.SimpleGui import init_display
display, start_display, add_menu, add_function_to_menu = init_display()
def pipe():
# the bspline path, must be a wire
# This will later be in a for loop but this is merely to validate the method
using three different points.
array = TColgp_Array1OfPnt(1,2)
makeWire = BRepBuilderAPI_MakeWire()
point1 = gp_Pnt(0,0,0)
point2 = gp_Pnt(0,0,1)
array.SetValue(1, point1)
array.SetValue(2, point2)
spline = GeomAPI_PointsToBSpline(array).Curve()
edge = BRepBuilderAPI_MakeEdge(spline).Edge()
makeWire.Add(edge)
point1 = gp_Pnt(0, 0, 1)
point2 = gp_Pnt(0, 1, 2)
array.SetValue(1, point1)
array.SetValue(2, point2)
spline = GeomAPI_PointsToBSpline(array).Curve()
edge = BRepBuilderAPI_MakeEdge(spline).Edge()
makeWire.Add(edge)
point1 = gp_Pnt(0, 1, 2)
point2 = gp_Pnt(0, 2, 2)
array.SetValue(1, point1)
array.SetValue(2, point2)
spline = GeomAPI_PointsToBSpline(array).Curve()
edge = BRepBuilderAPI_MakeEdge(spline).Edge()
makeWire.Add(edge)
makeWire.Build()
wire = makeWire.Wire()
# the bspline profile. Profile mist be a wire/face
point = gp_Pnt(0,0,0)
dir = gp_Dir(0,0,1)
circle = gp_Circ(gp_Ax2(point,dir), 0.2)
profile_edge = BRepBuilderAPI_MakeEdge(circle).Edge()
profile_wire = BRepBuilderAPI_MakeWire(profile_edge).Wire()
profile_face = BRepBuilderAPI_MakeFace(profile_wire).Face()
# pipe
pipe = BRepOffsetAPI_MakePipe(wire, profile_face).Shape()
display.DisplayShape(profile_edge, update=False)
display.DisplayShape(wire, update=True)
display.DisplayShape(pipe, update=True)
if __name__ == '__main__':
pipe()
start_display()
答案 0 :(得分:3)
虽然导线的边缘连接,但它们不能平滑过渡。 BrepOffsetAPI_MakePipe:
通过沿着电线Spine扫描形状轮廓来构造管道。脊柱与轮廓形成的角度沿着管道的长度保持。警告脊柱必须连续G1;也就是说,在导线的两个边缘的连接顶点上,左侧和右侧的切向量必须具有相同的方向,但不一定是相同的大小。
可以找到另一个连续性描述here,我们需要相切(G1)。如果两条相邻曲线的末端不相切,则扫描将无法保持相同的角度(脊柱与轮廓相同)。
最简单的解决方案是切割管道。
def pipe(point1, point2):
makeWire = BRepBuilderAPI_MakeWire()
edge = BRepBuilderAPI_MakeEdge(point1, point2).Edge()
makeWire.Add(edge)
makeWire.Build()
wire = makeWire.Wire()
dir = gp_Dir(point2.X() - point1.X(), point2.Y() - point1.Y(), point2.Z() - point1.Z())
circle = gp_Circ(gp_Ax2(point1,dir), 0.2)
profile_edge = BRepBuilderAPI_MakeEdge(circle).Edge()
profile_wire = BRepBuilderAPI_MakeWire(profile_edge).Wire()
profile_face = BRepBuilderAPI_MakeFace(profile_wire).Face()
pipe = BRepOffsetAPI_MakePipe(wire, profile_face).Shape()
display.DisplayShape(pipe, update=True)
if __name__ == '__main__':
pipe(gp_Pnt(0,0,0), gp_Pnt(0,0,1))
pipe(gp_Pnt(0,0,1), gp_Pnt(0,1,2))
pipe(gp_Pnt(0,1,2), gp_Pnt(0,2,2))
start_display()
我们可以添加球体来填补空白。
from OCC.BRepPrimAPI import BRepPrimAPI_MakeSphere
def sphere(centre, radius):
sphere = BRepPrimAPI_MakeSphere (centre, radius).Shape()
display.DisplayShape(sphere, update=True)
def pipe(point1, point2):
...
if __name__ == '__main__':
pipe(gp_Pnt(0,0,0), gp_Pnt(0,0,1))
sphere(gp_Pnt(0,0,1), 0.2)
pipe(gp_Pnt(0,0,1), gp_Pnt(0,1,2))
sphere(gp_Pnt(0,1,2), 0.2)
pipe(gp_Pnt(0,1,2), gp_Pnt(0,2,2))
start_display()
或者,您可以实现圆角算法,例如ChFi2d Class提供的算法。鉴于激光打印环境和算法的平面特征,我将点映射到xy平面。
from OCC.ChFi2d import ChFi2d_AnaFilletAlgo
def filletEdges(ed1, ed2):
radius = 0.3
f = ChFi2d_AnaFilletAlgo()
f.Init(ed1,ed2,gp_Pln())
f.Perform(radius)
return f.Result(ed1, ed2)
def pipe():
# the points
p1 = gp_Pnt(0,0,0)
p2 = gp_Pnt(0,1,0)
p3 = gp_Pnt(1,2,0)
p4 = gp_Pnt(2,2,0)
# the edges
ed1 = BRepBuilderAPI_MakeEdge(p1,p2).Edge()
ed2 = BRepBuilderAPI_MakeEdge(p2,p3).Edge()
ed3 = BRepBuilderAPI_MakeEdge(p3,p4).Edge()
# inbetween
fillet12 = filletEdges(ed1, ed2)
fillet23 = filletEdges(ed2, ed3)
# the wire
makeWire = BRepBuilderAPI_MakeWire()
makeWire.Add(ed1)
makeWire.Add(fillet12)
makeWire.Add(ed2)
makeWire.Add(fillet23)
makeWire.Add(ed3)
makeWire.Build()
wire = makeWire.Wire()
# the pipe
dir = gp_Dir(0,1,0)
circle = gp_Circ(gp_Ax2(p1,dir), 0.2)
profile_edge = BRepBuilderAPI_MakeEdge(circle).Edge()
profile_wire = BRepBuilderAPI_MakeWire(profile_edge).Wire()
profile_face = BRepBuilderAPI_MakeFace(profile_wire).Face()
pipe = BRepOffsetAPI_MakePipe(wire, profile_face).Shape()
display.DisplayShape(pipe, update=True)
if __name__ == '__main__':
pipe()
start_display()