question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Clipping a mesh, e.g. to a ball

See original GitHub issue

Hello,

I want to request a feature: the possibility to clip a mesh to a general region. Let me show you what I mean with an example.

Here is the Togliatti (iso)surface clipped to a box:

from math import sqrt
import numpy as np
import pyvista as pv

def f(x, y, z):
    return (
        64
        * (x - 1)
        * (
            x ** 4
            - 4 * x ** 3
            - 10 * x ** 2 * y ** 2
            - 4 * x ** 2
            + 16 * x
            - 20 * x * y ** 2
            + 5 * y ** 4
            + 16
            - 20 * y ** 2
        )
        - 5
        * sqrt(5 - sqrt(5))
        * (2 * z - sqrt(5 - sqrt(5)))
        * (4 * (x ** 2 + y ** 2 - z ** 2) + (1 + 3 * sqrt(5))) ** 2
    )

# generate data grid for computing the values
X, Y, Z = np.mgrid[(-5):5:200j, (-5):5:200j, (-4):4:200j]
# create a structured grid
grid = pv.StructuredGrid(X, Y, Z)

values = f(X, Y, Z)
grid.point_data["values"] = values.ravel(order="F")
# compute the isosurface f(x, y, z) = 0
isosurf = grid.contour(isosurfaces=[0])

mesh = isosurf.extract_geometry()
# surface clipped to the box:
mesh.plot(smooth_shading=True, color="hotpink")

Togliatti_pyvista_box

It is not highly pretty. You will see later that it is prettier when clipped to a ball (in particular it would be desirable to get rid of the non-connected components at the top).

A way to clip the surface to a ball consists in using remove_points:

# surface clipped to the ball of radius 4.8, with the help of `remove_points`:
lengths = np.linalg.norm(mesh.points, axis=1)
toremove = lengths >= 4.8
mesh2, idx = mesh.remove_points(toremove)
mesh2.plot(smooth_shading=True, color="hotpink")

Togliatti_pyvista_ball

That’s not too bad, but that’s not perfect: the borders are not smooth.

In the case of a ball, we can achieve a clipped surface with smooth borders by resorting to spherical coordinates:

from math import sqrt, pi
import numpy as np
import pyvista as pv

def f(ρ, θ, ϕ):
    x = ρ * np.cos(θ) * np.sin(ϕ)
    y = ρ * np.sin(θ) * np.sin(ϕ)
    z = ρ * np.cos(ϕ)
    return (
        64
        * (x - 1)
        * (
            x ** 4
            - 4 * x ** 3
            - 10 * x ** 2 * y ** 2
            - 4 * x ** 2
            + 16 * x
            - 20 * x * y ** 2
            + 5 * y ** 4
            + 16
            - 20 * y ** 2
        )
        - 5
        * sqrt(5 - sqrt(5))
        * (2 * z - sqrt(5 - sqrt(5)))
        * (4 * (x ** 2 + y ** 2 - z ** 2) + (1 + 3 * sqrt(5))) ** 2
    )

# generate data grid for computing the values
Rho, Theta, Phi = np.mgrid[0:4.8:200j, 0:pi:200j, 0:(2*pi):200j]
# create a structured grid
grid = pv.StructuredGrid(Rho, Theta, Phi)

values = f(Rho, Theta, Phi)
grid.point_data["values"] = values.ravel(order="F")
# compute the isosurface f(ρ, θ, ϕ) = 0
isosurf = grid.contour(isosurfaces=[0])
mesh = isosurf.extract_geometry()

# spherical to Cartesian:
def sph2cart(sph):
    ρ = sph[:, 0]
    θ = sph[:, 1]
    ϕ = sph[:, 2]
    return np.array([
        ρ * np.cos(θ) * np.sin(ϕ),
        ρ * np.sin(θ) * np.sin(ϕ),
        ρ * np.cos(ϕ)
    ])

mesh.points = np.transpose(sph2cart(mesh.points))
mesh.plot(smooth_shading=True, color="hotpink")

Now the borders are smooth:

Togliatti_pyvista_spherical

Well, the point I want to raise is that there’s no way in PyVista to properly clip a mesh to a given bounding region, or at least I didn’t find one. Is there such a feature available?

Such a feature is available in the R package rgl: clipMesh3d (this package is a wrapper of OpenGL). It would be nice to have this feature in PyVista.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
stlacommented, Jan 14, 2022

It is fine for this example. I’ve just published a blog post in which I mention this method : MeshClipping.

1reaction
akaszynskicommented, Jan 14, 2022

Nice blog post!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Clipping a mesh to a ball - General Usage - Julia Programming ...
Hello, It looks like Makie has no functionality to clip a 3d mesh to a ball (i.e. to discard the part of the...
Read more >
Clipping an isosurface to a ball, and more - R-bloggers
We will firstly show how to clip an isosurface to a ball with R, and then, more generally, how to clip a surface...
Read more >
Clipping fur meshes to not render through other meshes
Hello! I'm puzzled how to solve a problem with fur material (high level fur). I need to prevent it from rendering through adjacent...
Read more >
Random Clipping Through Mesh - Unity Forum
I have created a test scene in which a sphere that is set to roll over a mesh occasionally clips through the mesh....
Read more >
Meshes - Rive Guide
Meshes are an excellent way to add natural and organic deformations to raster ... In this example, we are adding the ball group...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found