Clipping a mesh to a ball

Hello,

It looks like Makie has no functionality to clip a 3d mesh to a ball (i.e. to discard the part of the mesh which is outside the ball). Is there another package to achieve that? Motivation. This is possible with the R package rgl, and with the C++ library CGAL. I took a look at CGAL.jl but didn’t found anything related to 3d meshes.

1 Like

ConstructiveGeometry.jl should provide the CSG operations you would need.

Here is a solution with Meshes.jl:

using Meshes, MeshViz

import PlyIO # for reading PLY files
import GLMakie as Mke # for visualization

# helper function to load mesh from PLY file
function readply(fname)
  ply = PlyIO.load_ply(fname)
  x = ply["vertex"]["x"]
  y = ply["vertex"]["y"]
  z = ply["vertex"]["z"]
  points = Point3.(x, y, z)
  connec = [connect(Tuple(c.+1)) for c in ply["face"]["vertex_indices"]]
  SimpleMesh(points, connec)
end

# download mesh from the web
file = download("https://raw.githubusercontent.com/juliohm/JuliaCon2021/master/data/beethoven.ply")

# read mesh from disk
mesh = readply(file)

viz(mesh)

# create a neighborhood with radius (and optional metric)
ball = MetricBall(2.0)

# create a search method, in this case ball search
searcher = BallSearch(mesh, ball)

# find the indices of the elements inside a ball centered at the origin
inds = search(Point(0.,0.,0.), searcher)

# lazy view of elements in the mesh
vmesh = view(mesh, inds)

viz(vmesh)

1 Like

Thank you. But the mesh you obtain has abrupt borders. With rgl or CGAL, the borders are refined. I will try on another example, perhaps this is specific to this example.

Thanks. Not sure. The clipping is not really a Boolean operation.

Ah maybe with the intersection… I’ve just tried with CGAL and the computation of the intersection fails with my example.

It sounds like the intersection is what you would want. Are you certain your mesh is manifold and the vertices are indexed uniquely? E.g. Some formats like STL discard topology, which makes CSG operations difficult.

My mesh self-intersects. If I modify it a little, it does not self-intersect anymore but the computation fails, I don’t know why.

Clipping with the intersection is a hammer to kill a fly. Clipping is easier than intersection. A guy made it manually in R here: r - How to clip an isosurface to a ball? - Stack Overflow.

Can you please elaborate on why the proposed solution with Meshes.jl doesn’t meet the requirements?

Take a look at my link. The borders of the clipped mesh are smooth. On the clipped Beethoven mesh, they are highly non-smooth.

Smoothness is a property of the mesh, if you want to have smoother borders you have to have more elements or curved elements. You are confusing things.

Now if you want the result to be a different mesh with curved elements than that is another thing. You can clip as I did but just viewing the original mesh or actually produce a new mesh with curved elements. That is not currently implemented.

I’m not confusing :slight_smile: The smoothness on the Togliatti example is not intrinsically due to the mesh. When clipping, the borders are refined, there are new faces. See the second link where the guy explains the method.

Look. I’ve clipped Beethoven with rgl, the borders are regular:

beethoven

I see. Feel free to submit PRs with a clipping method. We don’t have this operation defined yet, it deserves a new verb in the API. Our search methods only return a view of the original mesh:

https://juliageometry.github.io/Meshes.jl/stable/algorithms/neighborsearch.html

You can add a new clip verb and provide clipping methods.

Can you clip with a similar ball size? The ball you used in the R example is much larger.

This is similar with radius=2.

I’m really not familiar with meshes in Julia. It would be nice to use CGAL for the clipping. And I’m not familiar with the usage of C/C++ in Julia as well.

There’s also GitHub - rgcv/CGAL.jl: CGAL meets Julia, although the documentation is minimalist.

@_stla perhaps you should set radius=1 in the R version because clearly the clipping is different with radius=2.