[FIXED] Ticket #6407 - python API access to 2d fillet OCC functionality
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
[FIXED] Ticket #6407 - python API access to 2d fillet OCC functionality
Opencascade provides the algorythm ChFi2d_FilletAlgo which allows to create 2d fillets between two wires with numerical methods. Do we have access to this functionality from python? If not would it make sense to add it to the Part module?
Last edited by Kunda1 on Sat May 28, 2022 11:30 am, edited 2 times in total.
Reason: Solved by wmayer
Reason: Solved by wmayer
Re: 2d fillet
And who wants to do it?
With pythonocc it's possible to use this functionality, but not sure how to retrieve the resulting arc...
Code: Select all
radius = 1
from OCC import Core
api = Core.ChFi2d.ChFi2d_FilletAPI()
# w = ... wire in xy-plane
w_1 = Part.__toPythonOCC__(w)
w_2 = Core.TopoDS.topods_Wire(w_1)
pln = Core.gp.gp_Pln(Core.gp.gp_Pnt(0, 0, 0), Core.gp.gp_Dir(0, 0, 1))
api.Init(w_2, pln)
api.Perform(radius)
api.Result(????)
Re: 2d fillet
OCC is not part of condo.dmg (OS X). Did you see this example?
Re: 2d fillet
The example uses the analytic algorithm which doesn't work for all edges. As far as I understand the numeric method should also work on more complex edges like bsplines. So here is a working example. But I am not yet sure why the point is needed for the result.
Code: Select all
import numpy as np
import FreeCAD as App
import Part
from OCC.Core import ChFi2d
from OCC import Core
api = ChFi2d.ChFi2d_FilletAPI()
def pyocc_2d_fillet(e1, e2):
# asuming edges are in a plane
# extracting vertices
p1 = np.array([*e1.valueAt(e1.FirstParameter)])
p2 = np.array([*e1.valueAt(e1.LastParameter)])
p3 = np.array([*e2.valueAt(e2.FirstParameter)])
p4 = np.array([*e2.valueAt(e2.LastParameter)])
t1 = p2 - p1
t2 = p4 - p3
n = np.cross(t1, t2)
pln = Core.gp.gp_Pln(Core.gp.gp_Pnt(*p1), Core.gp.gp_Dir(*n))
occ_e1 = Core.TopoDS.topods_Edge(Part.__toPythonOCC__(e1))
occ_e2 = Core.TopoDS.topods_Edge(Part.__toPythonOCC__(e2))
api.Init(occ_e1, occ_e2, pln)
api.Perform(radius)
occ_p0 = Core.gp.gp_Pnt(0,0,0)
occ_arc = api.Result(occ_p0, occ_e1, occ_e2)
return Part.Wire([Part.__fromPythonOCC__(occ_e1),
Part.__fromPythonOCC__(occ_arc),
Part.__fromPythonOCC__(occ_e2)])
def test():
App.newDocument()
radius = 0.1
p0 = App.Vector(0,0,0)
p1 = App.Vector(1,0,0)
p2 = App.Vector(0,1,0)
e1 = Part.LineSegment(p1, p0).toShape()
e2 = Part.LineSegment(p0, p2).toShape()
Part.show(e1)
Part.show(e2)
Part.show(pyocc_2d_fillet(e1, e2))
test()
Last edited by looo on Fri Aug 21, 2020 8:57 am, edited 1 time in total.
Re: 2d fillet
It seems to be needed for choosing a solution, in case of multiple solutions :
https://www.opencascade.com/doc/occt-7. ... 3fd2e88967
Re: 2d fillet
But what is the point reffering to. Is it the center of the arc?Chris_G wrote: ↑Fri Aug 21, 2020 8:40 amIt seems to be needed for choosing a solution, in case of multiple solutions :
https://www.opencascade.com/doc/occt-7. ... 3fd2e88967
Also pythonocc-core is already available from conda-forge. But I am not sure if we should include it in the bundle. I guess this will add another ~100mb...
Re: 2d fillet
In your example is small mistake. The method pyocc_2d_fillet(e1, e2, r) missing the last parameter. In my testing the coords of occ_p0 has never changed. Maybe is really need complex example (e.g. 2x arcs) with two connection points.looo wrote: ↑Fri Aug 21, 2020 8:59 amBut what is the point reffering to. Is it the center of the arc?Chris_G wrote: ↑Fri Aug 21, 2020 8:40 amIt seems to be needed for choosing a solution, in case of multiple solutions :
https://www.opencascade.com/doc/occt-7. ... 3fd2e88967
Also pythonocc-core is already available from conda-forge. But I am not sure if we should include it in the bundle. I guess this will add another ~100mb...
Thx, pythonocc-core works fine. I think to add it in the bundle need other topic in the discussion forum.
Code: Select all
import numpy as np
import FreeCAD as App
import Part
from OCC.Core import ChFi2d
from OCC import Core
api = ChFi2d.ChFi2d_FilletAPI()
npt = None
def pyocc_2d_fillet(e1, e2, r):
# asuming edges are in a plane
# extracting vertices
p1 = np.array([*e1.valueAt(e1.FirstParameter)])
p2 = np.array([*e1.valueAt(e1.LastParameter)])
p3 = np.array([*e2.valueAt(e2.FirstParameter)])
p4 = np.array([*e2.valueAt(e2.LastParameter)])
t1 = p2 - p1
t2 = p4 - p3
n = np.cross(t1, t2)
pln = Core.gp.gp_Pln(Core.gp.gp_Pnt(*p1), Core.gp.gp_Dir(*n))
occ_e1 = Core.TopoDS.topods_Edge(Part.__toPythonOCC__(e1))
occ_e2 = Core.TopoDS.topods_Edge(Part.__toPythonOCC__(e2))
api.Init(occ_e1, occ_e2, pln)
if api.Perform(r) > 0:
occ_p0 = Core.gp.gp_Pnt(0,0,0)
occ_arc = api.Result(occ_p0, occ_e1, occ_e2)
global npt
npt = occ_p0
return Part.Wire([Part.__fromPythonOCC__(occ_e1),
Part.__fromPythonOCC__(occ_arc),
Part.__fromPythonOCC__(occ_e2)])
else:
return Part.Shape
def test():
App.newDocument()
radius = 0.1
p0 = App.Vector(1,0,0)
p1 = App.Vector(2,0.5,0)
p2 = App.Vector(1,1,0)
p3 = App.Vector(1,0,0)
e1 = Part.LineSegment(p1, p0).toShape()
e2 = Part.LineSegment(p3, p2).toShape()
Part.show(e1)
Part.show(e2)
Part.show(pyocc_2d_fillet(e1, e2, radius))
test()
FreeCAD.Console.PrintMessage(npt.Coord())
Re: 2d fillet
Ah I see, thanks for fixing this.
I have included it now. In my eyes it's good if people can have direct access to occ from python. This will further help to gather knowledge about occ. For example the minimal bounding box algorythm you found here: https://forum.freecadweb.org/viewtopic. ... 08#p425370
I tried to implement something like this for the unwrapping algorythm some time ago: https://github.com/FreeCAD/FreeCAD/blob ... x.cpp#L642 Actually this never worked properly so it is not used at all, but with the possibility to do this with occ it shouldn't be a big problem to align the patterns and later nest the bounding boxes...