I saw a couple of posts dicretizing the graphic and generate DelaunayMesh to get volume of 3D object. The issue I'm having is that DelaunayMesh creates a bigger solid covering the original one, resulting more volume. Please see the following.

Let's say I have this 3D solid defined as below. In spherical coordinate,

R[θ_, ϕ_] := Abs[Cos[θ]]^2

or in Cartesian system

pf[θ_, ϕ_] := {Sin[θ] Cos[ϕ], Sin[θ] Sin[ϕ], Cos[θ]}*R[θ, ϕ];

This object has two lobes as shown below.

plot = ParametricPlot3D[pf[θ, ϕ], {θ, 0, π}, {ϕ, 0, 2 π}]

enter image description here

where its volume from spherical integral is 0.598399,

NIntegrate[ρ^2 Sin[θ], {θ, 0, π}, {ϕ, 0, 2 π}, {ρ, 0, R[θ, ϕ]}]

After discretizing

displot = DiscretizeGraphics[Normal[plot /. (Lighting -> _) :> Lighting -> Automatic]]

I get

enter image description here

which still has two lobes, but with DelaunayMesh the feature disappears

hull = DelaunayMesh[MeshCoordinates[displot]]

enter image description here

And now it has different volume of 0.784115, greater than 0.598399 from the direct integration.


So I would like to know the best way to create mesh which gives the volume as precise as possible, both from a symbolic expression R(theta,phi) or from sampled points {{1,1,1},{3,2,2},....}.

One of the object I'm dealing with looks like this. Has many lobes, no symmetry.enter image description here

Here are more examples of distortion when I generate DelaunayMesh from a graphic.

From Parametricplot3D,

enter image description here

Then DelaunayMesh gives

enter image description here

  • $\begingroup$ Sorry, maybe there's something I'm missing, but why can't you just keep using your NIntegrate[ρ^2 Sin[θ], ...] method? $\endgroup$
    – user484
    Feb 25, 2015 at 8:04
  • $\begingroup$ If I had analytic expression for ρ, then I would do so. However I rather have discretized data points, basically a list of {ρ,θ,ϕ} coordinates. That's why I couldn't keep using NIntegrate. $\endgroup$
    – Xnei
    Feb 25, 2015 at 15:48
  • $\begingroup$ How did you generate the last plot? $\endgroup$
    – user484
    Feb 25, 2015 at 16:57
  • $\begingroup$ It is from ParametricPlot3D[pf//.sol[θ,ϕ] {θ, 0, π}, {ϕ, 0, 2 π}], where sol[θ,ϕ] is a solution from numerically solving differential equations. I can draw it from manually sampled points. In this case, I think interpolation is automatically done by Mathematica. However, distortion occurs when you convert the graphic to DelaunayMesh. $\endgroup$
    – Xnei
    Feb 25, 2015 at 18:28

2 Answers 2


DiscretizeGraphics already hands out a MeshRegion, so you could go along these lines:

meshonly = 
  With[{coords = MeshCoordinates[displot]}, 
    MeshCells[displot, 1] (* 0: points, 1: lines, 2: faces ... *) /. 
    Line[{a_, b_}] :> Line[{coords[[a]], coords[[b]]}]]


lines from MeshRegion extracted and displayed

This will also work for your the more exotic shape you displayed.


The volume can be calculated by calculating the volume of each tetraeder constructed from the mesh triangle with some fixed (for all calculations!) fourth point. The volume is either added or subtracted from the total volume, depending on the direction of the surface normal, which is given by the vertex ordering in Mathematica's output already, so you can go about this issue in the following way:

Total@With[{coords = MeshCoordinates[displot]}, 
   MeshCells[displot, 2] /. 
    Polygon[{a_, b_, c_}] :> 
     coords[[a]].Cross[coords[[b]], coords[[c]]]]/6
(* .585457 *)

The final divisor is required, since actually six volumes are calculated by the above operation.

The difference between the original result Mathematica provides and this one might be the effect of DiscreteGraphics.

It is possible to extract the actual polygons from the original plot, also, but one finds multi-vertex-polygons there (I did not check, if they are planar or convex or self-intersection-free), which require triangularization themselves, which is not all that difficult, but requires checking mentioned conditions and dealing with the situations encountered on a case-by-case-basis first, which I did not.

Nevertheless, I hope you can make some use of my answer!

Further reference: this publication

  • $\begingroup$ You can get a huge improvement out of this by applying Compile. I.e. creating a compiled function, say compiledDotCross, which simply takes the place of coords[[a]].Cross[coords[[b]], coords[[c]]]] and then applying this. For me that dropped computation time by over 20 times on a class of regions I use frequently. In fact, it rivals the built-in Volume when you do this. $\endgroup$
    – b3m2a1
    Jan 5, 2017 at 22:28

Are you sure NIntegrate won't work?

ρ[θ_?NumericQ,ϕ_?NumericQ] := sol[θ,ϕ]
SphericalPlot3D[ρ[θ,ϕ], {θ, 0, π}, {ϕ, 0, 2 π}]
NIntegrate[ρ[θ,ϕ]^3/3 Sin[θ], {θ, 0, π}, {ϕ, 0, 2 π}]

Assuming that sol[θ,ϕ] returns the value of your function.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.