occmodel is a Python library providing high-level access to OpenCASCADE, the C++ 3D modeling library powering FreeCAD. Personally, I mainly use occmodel to visualize and manipulate simple triangular meshes as for example provided by .off
files. This article discusses the installation of occmodel on Ubuntu and gives an examples in Python of how to visualize .off
files.
Installation
occmodel itself depends on:
where gltools and geotools have their own dependencies.
Unfortunately, the OpenCASCADE Community Edition (oce) available through the repositories is the wrong version. Therefore, oce is installed manually — the correct version to check out is oce-0.17.0
:
# manually install oce, as sudo apt-get install liboce-* will install oce 0.17 or later # which is not compatible with occmodel as it is cd ~ git clone https://github.com/tpaviot/oce oce-0.17.0 cd oce-0.17.0 git checkout OCE-0.17.0 # make sure to checkout 0.17.0! mkdir build cd build cmake .. make sudo make install
The above installation may take some time and assumes build-essentials
and cmake
to be installed. gltools additionally depends on GLFW. If libglfw3-dev
is not available through the repositories (e.g. on Ubuntu 14.04), it can be installed following this issue:
echo "deb http://ppa.launchpad.net/keithw/glfw3/ubuntu trusty main" | sudo tee -a /etc/apt/sources.list.d/fillwave_ext.list echo "deb-src http://ppa.launchpad.net/keithw/glfw3/ubuntu trusty main" | sudo tee -a /etc/apt/sources.list.d/fillwave_ext.list sudo apt-get update sudo apt-get install libglfw3 libglfw3-dev
gltools, geotools and occmodel additionally require Cython:
pip install cython
Then, geotools can be installed as follows:
cd ~ git clone https://github.com/tenko/geotools geotools-master cd geotools-master python setup.py build sudo python setup.py install
And gltools is installed analogously:
cd ~ git clone https://github.com/tenko/gltools gltools-master cd gltools-master/ python setup_build.py build sudo python setup_build.py install
Both installations can be check using:
python >>> import geotools >>> import gltools
If the latter gives rise to undefined GLFW functions, this might be a clue that the install version is not GLFW3. To finally install occmodel, the corresponding setup_build.py
needs to be adapted. For checking out occmodel:
cd ~ git clone https://github.com/tenko/occmodel occmodel-master
First, around line 47, the TKAdvTools
library needs to be removed:
OCC = \ '''FWOSPlugin PTKernel TKBO TKBRep TKBinL TKBool TKCDF TKFeat TKFillet TKG2d TKG3d TKGeomAlgo TKGeomBase TKHLR TKIGES TKLCAF TKMath TKMesh TKOffset TKPLCAF TKPShape TKPrim TKSTEP TKSTEP209 TKSTEPAttr TKSTEPBase TKSTL TKShHealing TKShapeSchema TKStdLSchema TKTObj TKTopAlgo TKXMesh TKXSBase TKXmlL TKernel '''
Second, the correct include directory for oce needs to be set. For Ubuntu, this is around line 70:
else: SOURCES += glob.glob("occmodel/@src/*.cpp") OCCINCLUDE = '/usr/local/include/oce' OCCLIBS = OCC.split() COMPILE_ARGS.append("-fpermissive")
Now, occmodel can be built:
cd ~/occmodel-master python setup_build.py build sudo python setup_build.py install
The installation can again be checked by importing occmodel in Python.
Reading OFF Files
The Object File Format is a text-based format to save triangular meshes consisting of vertices and triangular faces. The file format looks as follows:
OFF numVertices numFaces numEdges x_1, y_1, z_1 x_2, y_2, z_2 ... n_1 v_11 v_12 ... v_1n_1 n_2 v_21 b_22 ... v_2n_2 ...
The format gets clearer when looking at the following Python function to read .off
files:
import os import sys def read_off(file): """ Reads vertices and faces from an off file. :param file: path to file to read :type file: str :return: vertices and faces as lists of tuples :rtype: [(float)], [(int)] """ assert os.path.exists(file) with open(file, 'r') as fp: lines = fp.readlines() lines = [line.strip() for line in lines] assert lines[0] == 'OFF' parts = lines[1].split(' ') assert len(parts) == 3 num_vertices = int(parts[0]) assert num_vertices > 0 num_faces = int(parts[1]) assert num_faces > 0 vertices = [] for i in range(num_vertices): vertex = lines[2 + i].split(' ') vertex = [float(point) for point in vertex] assert len(vertex) == 3 vertices.append(vertex) faces = [] for i in range(num_faces): face = lines[2 + num_vertices + i].split(' ') face = [int(index) for index in face] assert face[0] == len(face) - 1 for index in face: assert index >= 0 and index < num_vertices assert len(face) > 1 faces.append(face) return vertices, faces
Visualizing Meshes
Visualizing a triangular mesh given an .off
file reduces to reading all the faces from the file and reconstructing the mesh face-by-face using Face().createPolygonal(real_face)
where Face
is provided by occmodel:
from occmodelviewer import viewer from occmodel import Face, Solid, OCCError import os import sys # read_off definition if __name__ == '__main__': if len(sys.argv) != 2: print('Usage: python view_off.py off_file') exit(1) off_file = sys.argv[1] assert os.path.exists(off_file) vertices, faces = read_off(off_file) real_faces = [] for face in faces: points = [] for i in range(1, len(face), 1): points.append(vertices[face[i]]) real_faces.append(points) occfaces = [] for real_face in real_faces: if len(real_face) == 3: try: occfaces.append(Face().createPolygonal(real_face)) except OCCError as e: print(e, real_face) else: assert(False) viewer(occfaces)
Visualizations of this cuboid, this chair and this monitor (taken from ModelNet) are shown in Figure 1.