Part.__fromPythonOCC__ issue : Segmentation fault

About the development of the Part Design module/workbench. PLEASE DO NOT POST HELP REQUESTS HERE!
User avatar
Cyril
Posts: 64
Joined: Wed Aug 23, 2017 5:04 pm
Location: Geneva (Switzerland)
Contact:

Part.__fromPythonOCC__ issue : Segmentation fault

Postby Cyril » Wed Jul 03, 2019 8:41 am

Hi,
OS: Manjaro Linux (XFCE/xfce)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19 (Git)
Build type: Release
Branch: master
Hash: fd5df98b6a10c63a378cd0869a2e60f3bd2a0516
Python version: 3.7.3
Qt version: 5.12.3
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: French/France (fr_FR)
FreeCAD crash while trying to create Part object from PythonOCC.

Steps to reproduce :
  1. Create a new document
  2. Switch to Part workbench
  3. Execute code below
  4. FreeCAD crash with error message below
Code snippet :

Code: Select all

import ifcopenshell
import ifcopenshell.geom

ifc_path = "TestModel_ACAD.ifc"
ifc_file = ifcopenshell.open(ifc_path)
s = ifcopenshell.geom.settings()
s.set(s.USE_PYTHON_OPENCASCADE, True)
s.set(s.USE_WORLD_COORDS, True)
s.set(s.INCLUDE_CURVES, True)
s.set(s.USE_BREP_DATA, True)
space_boundaries = ifc_file.by_type('IfcRelSpaceBoundary')

doc = FreeCAD.ActiveDocument

for space_boundary in (b for b in space_boundaries if b.Name == "2ndLevel"):
    outer_boundary = space_boundary.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary
    occ_shape = ifcopenshell.geom.create_shape(s, outer_boundary)
    face = Part.__fromPythonOCC__(occ_shape)
    Part.show(face)
Error message in terminal :

Code: Select all

Program received signal SIGSEGV, Segmentation fault.
Erreur de segmentation (core dumped)
Attached :
  • log
  • sample file
Attachments
TestModel_ACAD.ifc.zip
(38.21 KiB) Downloaded 9 times
FreeCAD.log
(9.79 KiB) Downloaded 10 times
I blog about HVAC / BIM / Energy : pythoncvc.net. If you like you can follow the RSS feed.
wmayer
Site Admin
Posts: 14644
Joined: Thu Feb 19, 2009 10:32 am

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby wmayer » Wed Jul 03, 2019 5:55 pm

The only thing I can imagine is that pythonocc for ifcopenshell was built with a different swig version compared to FreeCAD. Can find out which swig version pythonocc was built for?

An alternative way for using Part.__fromPythonOCC__ is to save the shape to disk and then read it back with Part.Shape.read
User avatar
Cyril
Posts: 64
Joined: Wed Aug 23, 2017 5:04 pm
Location: Geneva (Switzerland)
Contact:

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby Cyril » Thu Jul 04, 2019 4:36 am

wmayer wrote:
Wed Jul 03, 2019 5:55 pm
The only thing I can imagine is that pythonocc for ifcopenshell was built with a different swig version compared to FreeCAD. Can find out which swig version pythonocc was built for?
I have currently an issue recompiling ifcopenshell so I need to fix this before being able to test that.
wmayer wrote:
Wed Jul 03, 2019 5:55 pm
An alternative way for using Part.__fromPythonOCC__ is to save the shape to disk and then read it back with Part.Shape.read
Ok, I'll give it a try. How do you save a shape to disk ? PythonOCC and ifcopenshell documentations are quite light I struggle to find how to do stuff (I will do some wiki page/blog post about when I will have a better overview about it).
I blog about HVAC / BIM / Energy : pythoncvc.net. If you like you can follow the RSS feed.
wmayer
Site Admin
Posts: 14644
Joined: Thu Feb 19, 2009 10:32 am

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby wmayer » Thu Jul 04, 2019 7:36 am

I haven't used pythonocc for many years so I don't remember its package structure. But it's pretty much a 1:1 wrapper of the C++API so the class/method names are identical.

In C++ we have the static function BRepTools::Write which needs two parameters: the shape and the file name. So, I guess in Python it's probably BrepTools.Write(occ_shape, "/tmp/shape.brep")
User avatar
Cyril
Posts: 64
Joined: Wed Aug 23, 2017 5:04 pm
Location: Geneva (Switzerland)
Contact:

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby Cyril » Sun Jul 14, 2019 11:57 pm

wmayer wrote:
Thu Jul 04, 2019 7:36 am
I haven't used pythonocc for many years so I don't remember its package structure. But it's pretty much a 1:1 wrapper of the C++API so the class/method names are identical.

In C++ we have the static function BRepTools::Write which needs two parameters: the shape and the file name. So, I guess in Python it's probably BrepTools.Write(occ_shape, "/tmp/shape.brep")
Thanks a lot for your answer.
  1. I have been able to write to temp file then read it but I still get Segmentation Fault Error. On a second thought it seems logic as it is still the same pythonOCC which write and read the geometry.

    Code: Select all

        occ_shape = ifcopenshell.geom.create_shape(s, outer_boundary)
        tmp_file = "/tmp/shape.brep"
        OCC.BRepTools.breptools_Write(occ_shape, tmp_file)
        occ_shape = OCC.TopoDS.TopoDS_Face()
        builder = OCC.BRep.BRep_Builder()
        OCC.BRepTools.breptools_Read(occ_shape, tmp_file, builder)
        face = Part.__fromPythonOCC__(occ_shape)
  2. It made me realize that I don't need to recompile IfcOpenShell but only pythonOCC because IfcOpenShell use pythonOCC directly. So I recompiled successively FreeCAD and pythonOCC so they are now compiled with the same SWIG version. Unfortunately I still get the same error. Could it be more related to the fact that pythonOCC is built on OCE (OCCT 6.9.1) and FreeCAD built on OCCT 7.3 ?
  3. On a third thought… :lol: I realized that Part API has a function to read from file what you probably meant to read shape using this function and it worked !

    Code: Select all

    for space_boundary in (b for b in space_boundaries if b.Name == "2ndLevel"):
        outer_boundary = space_boundary.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary
        occ_shape = ifcopenshell.geom.create_shape(s, outer_boundary)
        tmp_file = "/tmp/shape.brep"
        OCC.BRepTools.breptools_Write(occ_shape, tmp_file)
        shape = Part.read(tmp_file)
        face = Part.Face(shape.Wires)
        Part.show(face)
But not being able to directly use generated TopoDS is still an issue. According from what I understood from Yorik post it is a bottleneck in IFC importation.
I blog about HVAC / BIM / Energy : pythoncvc.net. If you like you can follow the RSS feed.
wmayer
Site Admin
Posts: 14644
Joined: Thu Feb 19, 2009 10:32 am

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby wmayer » Mon Jul 15, 2019 8:53 am

occ_shape = ifcopenshell.geom.create_shape(s, outer_boundary)
tmp_file = "/tmp/shape.brep"
OCC.BRepTools.breptools_Write(occ_shape, tmp_file)
occ_shape = OCC.TopoDS.TopoDS_Face()
builder = OCC.BRep.BRep_Builder()
OCC.BRepTools.breptools_Read(occ_shape, tmp_file, builder)
face = Part.__fromPythonOCC__(occ_shape)
Reading back the shape with pythonocc makes no sense. Here you should use FreeCAD's Python API to get the shape. The whole idea of writing and reading the shape is to bypass the direct conversion of the pythonocc wrapper because this apparently fails due to some incompatible OCE/OCCT versions.
Could it be more related to the fact that pythonOCC is built on OCE (OCCT 6.9.1) and FreeCAD built on OCCT 7.3 ?
Of course. It's not possible to use OCE and OCCT within the same application because they are binary incompatible which leads to undefined behaviour.
So you have to make sure to either use OCE or OCCT for pythonocc and FreeCAD but not to mix them.
On a third thought… :lol: I realized that Part API has a function to read from file what you probably meant to read shape using this function and it worked !
I see you got it!
User avatar
Cyril
Posts: 64
Joined: Wed Aug 23, 2017 5:04 pm
Location: Geneva (Switzerland)
Contact:

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby Cyril » Thu Aug 01, 2019 9:05 am

Just for records. Considering PythonOCC state, there is a better way without using PythonOCC and need to use a temp file. IfcOpenShell USE_BREP_DATA setting without USE_PYTHON_OPENCASCADE produce a geometry object containing a brep_data string parameter which contain the geometry in an OCCT Brep format so we can use :

Code: Select all

occ_shape = shape.geometry.brep_data
fc_shape = Part.Shape()
fc_shape.importBrepFromString(occ_shape)
scale_factor = 1000
matrix = FreeCAD.Matrix()
matrix.scale(scale_factor, scale_factor, scale_factor)
fc_part = doc.addObject("Part::Feature", "IfcPart")
fc_part.Shape = fc_shape.transformGeometry(matrix)
I blog about HVAC / BIM / Energy : pythoncvc.net. If you like you can follow the RSS feed.
User avatar
bernd
Posts: 8238
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby bernd » Thu Aug 01, 2019 8:15 pm

it is similar to what we gone do in Arch module to import geometry from ifcopenshell ...

https://github.com/FreeCAD/FreeCAD/blob ... #L540-L551

by the way it is possible to import any sub shape as well. For example a profile which is used in an extrusion. See https://sourceforge.net/p/ifcopenshell/ ... 4d3b/#16f1
User avatar
bernd
Posts: 8238
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby bernd » Thu Aug 01, 2019 8:21 pm

the code I have been using for years to test if geometry from ifc imports into FreeCAD ...

Code: Select all

import ifcopenshell
from ifcopenshell import geom
settings = ifcopenshell.geom.settings()
settings.set(settings.USE_BREP_DATA,True)
settings.set(settings.SEW_SHELLS,True)
settings.set(settings.USE_WORLD_COORDS,True)
settings.set(settings.INCLUDE_CURVES,True)     # for stuct


file_path = '/home/hugo/Desktop/FreeCAD--forum/0112--dlubal--ifc/'
#file_path = 'C:\\Users\\bhb\\Downloads\\'
f = ifcopenshell.open(file_path + 'E1--3-Axis-Struc-Export.ifc')
f.by_type('IfcPerson')


#entity = f.by_id(77)  # is the first one in this file
#entity = f.by_type('IfcWall')[0]  # takes the first found
entity = f.by_type('IfcStructuralCurveMember')[0]  # takes the first found


print entity
cr = ifcopenshell.geom.create_shape(settings, entity)
brep = cr.geometry.brep_data
print brep

import Part
shape = Part.Shape()
shape.importBrepFromString(brep)
Part.show(shape)
User avatar
bernd
Posts: 8238
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland

Re: Part.__fromPythonOCC__ issue : Segmentation fault

Postby bernd » Thu Aug 01, 2019 8:22 pm

https://github.com/FreeCAD/FreeCAD/blob ... FC.py#L551

Code: Select all

shape.scale(1000.0) # IfcOpenShell always outputs in meters, we convert to mm, the freecad internal unit
might be simpler than the matrix one ...