5

I am parsing a 3D mesh from .obj using pywavefront which gives me vertices, faces and normals. I want to calculate the remaining area from subtracting another mesh.

Following up on calculating volume I wonder how can I perform operations on the meshes such as intersect and subtract.

high_byte
  • 261
  • 3
  • 7

3 Answers3

3

If I understand correctly, in order to get the volume of your remaining area you should first compute the resulting mesh. This is known as boolean operations which are often implemented on envelopes (surface mesh like in the .obj files)

There is several python modules proposing implementations for boolean operation on meshes.

  • pymesh exposes the algorithms of CGAL (c++ library)
  • pymadcad with a different algorithm in pure python
  • blender which is a complete software but which provide boolean operations in their API
  • trimesh relying on CGAL and Blender

there is few other modules but - as far as I know - all of them are relying on pymesh or blender under the coat.

jimy byerley
  • 129
  • 1
  • 6
  • thank you for your reply! I ended up using Blender (some time ago actually) but thanks for the links, it is still interesting to learn about these. – high_byte Dec 13 '20 at 16:05
2

I would like to mention other two very interesting and powerful libraries:

  • pymeshlab: a Python library that interfaces to MeshLab, the popular open source application for editing and processing large 3D triangle meshes.
  • pyvista: a high-level Python API to the Visualization Toolkit (VTK).

Both libraries allows to perform boolean operations between meshes. Let's consider the intersection between the Stanford bunny (~86k triangles) and a sphere:

enter image description here

The code below compare the intersection and computational time of the two libraries.

from time import perf_counter

import pymeshlab
import pyvista as pv
import trimesh

bunny_path = "bunny.ply"
sphere_path = "sphere.ply"


def pymeshlab_intersection() -> None:

    ms = pymeshlab.MeshSet()
    ms.load_new_mesh(bunny_path)
    ms.load_new_mesh(sphere_path)
    ms.generate_boolean_intersection()
    ms.save_current_mesh("pymeshlab_intersection.ply")
    intersection_volume = ms.get_geometric_measures()["mesh_volume"]
    print(f"pymeshlab - intersection volume = {intersection_volume}")


def pyvista_intersection() -> None:

    bunny = trimesh.load_mesh(bunny_path, process=False, maintain_order=True)
    bunny_pv = pv.wrap(bunny)
    sphere = trimesh.load_mesh(sphere_path, process=False, maintain_order=True)
    sphere_pv = pv.wrap(sphere)
    intersection = bunny_pv.boolean_intersection(sphere_pv)
    intersection.save("pyvista_intersection.ply")
    print(f"pyvista - intersection volume = {intersection.volume}")


if __name__ == "__main__":

    t0 = perf_counter()
    pymeshlab_intersection()
    print(f"pymeshlab: {perf_counter() - t0} s")

    t0 = perf_counter()
    pyvista_intersection()
    print(f"pyvista: {perf_counter() - t0} s")

pymeshlab:

  • intersection volume: 14799.202211491009
  • elapsed time: 2.1220125 s

pyvista:

  • intersection volume: 14799.297891938557
  • elapsed time: 4.3342883 s

So, pymeshlab is twice as fast as pyvista.

Below the resulting mesh created by pymeshlab: enter image description here

blunova
  • 2,122
  • 3
  • 9
  • 21
1

Just to add to the existing answer, that one more option is to use open-source library MeshLib having Python interface. It can read and write meshes in Wavefront format (.obj) and perform Boolean operations on meshes.

For example, the code for subtracting a torus from a cube is as follows:

import meshlib.mrmeshpy as mr
# create a mesh of cube with edge length =1:
cube = mr.makeCube(size = mr.Vector3f( 1, 1, 1 ))
# create a mesh of torus:
torus = mr.makeTorus( primaryRadius = 0.65, secondaryRadius = 0.1 )
# compute the difference between the cube and the torus:
diff = mr.boolean( cube, torus, mr.BooleanOperation.DifferenceAB )
# save the difference in file:
mr.saveMesh(diff.mesh, mr.Path("diff.obj"))

The difference mesh after opening in some mesh viewer: enter image description here

Fedor
  • 17,146
  • 13
  • 40
  • 131
  • 1
    thank you this is awesome. my original intention was to calculate volume differences and use that as a loss function for 3D objects synthesis. there have been some nice papers in this field since then. – high_byte Oct 01 '22 at 07:30