Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonocc/Opencascade | Create pipe along straight lines through points, profile wont change normal

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()
like image 679
Sander Voss Avatar asked Nov 07 '17 17:11

Sander Voss


1 Answers

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).

pipeNot

The easiest solution is to cut the pipe.

pipeChop

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.

pipeSphere

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.

pipeFill

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()
like image 52
Funk Avatar answered Sep 28 '22 08:09

Funk