Pythonocc/Opencascade | Создайте трубопровод по прямым линиям через точки, профиль не изменит нормальный

Моя конечная цель такова:

У меня есть огромный набор данных из точек, представляющий, как часть будет печататься трехслойно. Мне нужно создать линию через эти точки и выдавить круг вдоль этой линии (так что перестройте часть, как она будет напечатана позже).

Сначала я попытался сделать сплайн, однако он пытается создать плавную линию и не следует за точками. Я попытался изменить параметры minDeg и maxDeg, но это все равно не помогло создать фактическую кривую, в которой я нуждаюсь.

Посмотрите этот результат для сплайна

См. здесь фактический путь (вышеупомянутый сплайн - одна из частей заполнения)

Итак, я попытался создать сплайн между двумя точками за раз, а затем, создав провод, добавьте их все вместе. Это выглядит многообещающим, так как теперь я получаю реальные острые углы и линии, проходящие через точные точки. Однако теперь, когда я пытаюсь выдавить его, нормаль экструдированного профиля не изменяется с углом провода.

Это то, что происходит с последней вещью, которую я пробовал.

Я провел последние 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()

Ответ 1

Хотя края провода соединяются, они не плавно переходят. BrepOffsetAPI_MakePipe:

Создает трубу путем подметания профиля профиля вдоль проволоки. Угол, создаваемый позвоночником с профилем, поддерживается вдоль длины трубы. Предупреждение Позвоночник должен быть G1 непрерывным; т.е. на вершине соединения двух ребер провода, касательные векторы слева и справа должны иметь одно и то же направление, хотя и не обязательно одинаковое.

Следующее описание непрерывности можно найти здесь, нам нужно касание (G1). Если две соседние кривые arent касаются на концах, развертка не сможет поддерживать тот же угол (сделанный позвоночником с профилем).

pipeNot

Самое простое решение - отрезать трубку.

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

Мы можем добавить сферы для устранения пробелов.

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

В качестве альтернативы вы можете реализовать алгоритм филе, например, предоставленный ChFi2d Class. Учитывая контекст лазерной печати и плоский характер алгоритма, Ive сопоставил точки с плоскостью xy.

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