pythonocc-core icon indicating copy to clipboard operation
pythonocc-core copied to clipboard

Segfault with read_stl_file

Open vyeevani opened this issue 2 years ago • 4 comments

Reading STL files is causing segfaults.

I used the stl file from the demo script as well as a 3dbenchy.stl from thingiverse and reproed with both .

This is the script I tried running:

import faulthandler
faulthandler.enable()

from OCC.Extend.DataExchange import read_stl_file
read_stl_file('five_spoke_wheel.stl')

Here's the backtrace I collected:

% lldb python3 untitled.py 
(lldb) target create "python3"
Current executable set to 'python3' (arm64).
(lldb) settings set -- target.run-args  "untitled.py"
(lldb) r
Process 35603 launched: '/Users/vineethyeevani/opt/miniconda3/envs/pyoccenv/bin/python3' (arm64)
Process 35603 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x91951c1e0)
    frame #0: 0x00000001078a2b68 libTKTopAlgo.7.7.0.dylib`___lldb_unnamed_symbol1398$$libTKTopAlgo.7.7.0.dylib + 296
libTKTopAlgo.7.7.0.dylib`___lldb_unnamed_symbol1398$$libTKTopAlgo.7.7.0.dylib:
->  0x1078a2b68 <+296>: ldr    x10, [x10, w23, uxtw #3]
    0x1078a2b6c <+300>: cbz    x10, 0x1078a2b88          ; <+328>
    0x1078a2b70 <+304>: ldp    w11, w12, [x10, #0x20]
    0x1078a2b74 <+308>: cmp    w11, w8
Target 0: (python3) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x91951c1e0)
  * frame #0: 0x00000001078a2b68 libTKTopAlgo.7.7.0.dylib`___lldb_unnamed_symbol1398$$libTKTopAlgo.7.7.0.dylib + 296
    frame #1: 0x00000001078a1858 libTKTopAlgo.7.7.0.dylib`BRepBuilderAPI_MakeShapeOnMesh::Build(Message_ProgressRange const&) + 2296
    frame #2: 0x00000001067a1338 libTKSTL.7.7.0.dylib`StlAPI_Reader::Read(TopoDS_Shape&, char const*) + 172
    frame #3: 0x00000001067a117c libTKSTL.7.7.0.dylib`StlAPI::Read(TopoDS_Shape&, char const*) + 44
    frame #4: 0x0000000138745c1c _StlAPI.so`_wrap_stlapi_Read(_object*, _object*) + 244
    frame #5: 0x000000010009d7b0 python3`cfunction_call + 208
    frame #6: 0x000000010004eb00 python3`_PyObject_Call + 164
    frame #7: 0x000000010013b850 python3`_PyEval_EvalFrameDefault + 26808
    frame #8: 0x0000000100134950 python3`_PyEval_EvalCode + 2832
    frame #9: 0x000000010004ed14 python3`_PyFunction_Vectorcall + 220
    frame #10: 0x000000010013ee5c python3`call_function + 516
    frame #11: 0x000000010013b5a8 python3`_PyEval_EvalFrameDefault + 26128
    frame #12: 0x000000010004edd0 python3`function_code_fastcall + 116
    frame #13: 0x000000010013ee5c python3`call_function + 516
    frame #14: 0x000000010013b5a8 python3`_PyEval_EvalFrameDefault + 26128
    frame #15: 0x0000000100134950 python3`_PyEval_EvalCode + 2832
    frame #16: 0x000000010018e5fc python3`run_mod + 216
    frame #17: 0x000000010018c174 python3`pyrun_file + 264
    frame #18: 0x000000010018b99c python3`PyRun_SimpleFileExFlags + 1332
    frame #19: 0x00000001001ae3b4 python3`Py_RunMain + 2148
    frame #20: 0x00000001001af500 python3`pymain_main + 1204
    frame #21: 0x0000000100001844 python3`main + 56
    frame #22: 0x00000001003d9088 dyld`start + 516

vyeevani avatar Sep 06 '23 15:09 vyeevani

I should also mention that I tried this on my local machine (arm64 MacBook) plus the binder environment mentioned in the readme

vyeevani avatar Sep 06 '23 15:09 vyeevani

If anyone else has this issue, I ended up working around this with the following:

from tqdm import tqdm

import numpy as np
from stl import mesh
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakePolygon, BRepBuilderAPI_MakeFace
from OCC.Core.TopoDS import TopoDS_Compound, TopoDS_Builder
from OCC.Core.gp import gp_Pnt

def stl_to_shape(stl_filename):
    # Read the STL using numpy-stl
    stl_mesh = mesh.Mesh.from_file(stl_filename)
    
    # Create an empty compound to hold the resulting triangles
    compound = TopoDS_Compound()
    builder = TopoDS_Builder()
    builder.MakeCompound(compound)
    
    # Iterate over the facets in the STL
    for facet in tqdm(stl_mesh.vectors, desc="processing facets"):
        # Create a polygon for each triangle in the STL
        polygon = BRepBuilderAPI_MakePolygon()
        for vertex in facet:
            x, y, z = map(float, vertex)
            polygon.Add(gp_Pnt(x, y, z))
        polygon.Close()
        
        # Create a face from the polygon and add it to the compound
        face = BRepBuilderAPI_MakeFace(polygon.Wire()).Face()
        builder.Add(compound, face)
    
    return compound

vyeevani avatar Sep 06 '23 16:09 vyeevani

I confirm the bug, it also segfaults on my machine.

tpaviot avatar Sep 22 '23 12:09 tpaviot

You can try the MeshDS_DataSource class?

from OCC.Core.MeshDS import MeshDS_DataSource
from OCC.Core.RWStl import rwstl

import numpy as np

a_stl_mesh = rwstl.ReadFile("five_spoke_wheel")
mesh_ds =  MeshDS_DataSource(a_stl_mesh)

bb = mesh_ds.GetBoundingBox().Get()

You can have a look at https://github.com/tpaviot/pythonocc-core/blob/master/test/core_meshdatasource_unittest.py

tpaviot avatar Sep 22 '23 13:09 tpaviot

doesn't segfault anymore using current master branch (occt7.8.1)

tpaviot avatar May 13 '24 09:05 tpaviot