My ultimate goal is as follows:
I have a huge data set of points, representing how a part will be 3D printed layer by layer. I need to create a line through these points and extrude a circle along this line (so rebuild the part as it will be printed later).
I initially tried doing a spline, however this attempts to create a smooth line and does not follow the points at all. I attempted changing the minDeg and maxDeg options but this still didn't help enough to create the actual curve I need.
See this result for the spline
See here the actual path (the above spline is one of the infill parts)
So I have attempted creating a spline between just two points at a time, then when creating a wire add them all together. This looks promising as now I do get actual sharp corners and the lines going through the exact points. However, now when I try to extrude along it the normal of the extruded profile does not change with the angle of wire.
This is what happens with the last thing I tried
I have spent my last 4 days on this problem, tried many forums and questions but feel completely lost in the world of pythonocc (opencascade).
My code reads as follows:
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()
Though the edges of the wire connect, they don’t transition smoothly. BrepOffsetAPI_MakePipe:
Constructs a pipe by sweeping the shape Profile along the wire Spine. The angle made by the spine with the profile is maintained along the length of the pipe. Warning Spine must be G1 continuous; that is, on the connection vertex of two edges of the wire, the tangent vectors on the left and on the right must have the same direction, though not necessarily the same magnitude.
Another continuity description can be found here, we need tangency (G1). If two adjacent curves aren’t tangent at the ends, the sweep won’t be able to maintain the same angle (made by the spine with the profile).
The easiest solution is to cut the pipe.
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()
We can add spheres to bridge the gaps.
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()
Alternatively, you could implement a fillet algorithm, such as those provided by the ChFi2d Class. Given the laser printing context and the planar character of the algorithm, I’ve mapped the points to the xy-plane.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With