1
$\begingroup$
ListContourPlot3D[
 Table[x^2 + y^2 + z^2, {x, -1, 1, 0.02}, {y, -1, 1, 0.02}, {z, -1, 1,
    0.02}], Contours -> {1}, Mesh -> None]

will generate plot as below

enter image description here

Notice the red circles. Why are there speckles on the surface? How to remove them and get a perfect surface?

$\endgroup$
5
  • $\begingroup$ I doubt that you will ever get a perfect surface; however, I suggest that you start with the option PerformanceGoal -> "Quality" $\endgroup$
    – Bob Hanlon
    Commented Sep 18, 2021 at 13:31
  • $\begingroup$ @BobHanlon Thank you for reply. But PerformanceGoal -> "Quality" has no effect at all. $\endgroup$
    – matheorem
    Commented Sep 18, 2021 at 13:44
  • 1
    $\begingroup$ MaxPlotPoints ->60 ? The default is Infinity. $\endgroup$
    – Syed
    Commented Sep 18, 2021 at 14:06
  • $\begingroup$ @Syed Thank you for reply. MaxPlotPoints ->60 seems works. But why does it work? $\endgroup$
    – matheorem
    Commented Sep 18, 2021 at 14:15
  • 1
    $\begingroup$ No idea. In the Details section for MaxPlotPoints it says, "With finite settings for MaxPlotPoints, the total number of points plotted is reduced by combining nearby points." Since there were only two settings, I applied the other one to see what would happen. $\endgroup$
    – Syed
    Commented Sep 18, 2021 at 14:19

1 Answer 1

5
$\begingroup$

The second update at the end is probably the best solution when ListContourPlot3D produces bad shading.

First answer, with update

One source of strange shading is bad VertexNormals. They have to be estimated from the data, and if they "wobble" from true normal, the surface's shading changes slightly.

On the test example, we "know" what the surface normal should be. We fix it to show that it fixes the shading. For real data, it seems unusual to know how calculate exactly the normals.

GraphicsRow[{
  foo = ListContourPlot3D[Table[x^2 + y^2 + z^2,
     {x, -1, 1, 0.02}, {y, -1, 1, 0.02}, {z, -1, 1, 0.02}],
    Contours -> {1}, Mesh -> None], 
  foo /. 
   GraphicsComplex[p_, a___, HoldPattern[VertexNormals -> _], b___] :>
     GraphicsComplex[p, a, 
     VertexNormals -> Transpose[Transpose@p - 50], b]
  },
 ImageSize -> 800]

enter image description here

These are easier ways to fix it, but (update) they just remove the vertex normals, which I didn't notice because of the fineness of the mesh:

DeleteCases[foo, HoldPattern[VertexNormals -> _], Infinity]
RegionPlot3D[DiscretizeGraphics[foo]]
(* each produces graphics like this: *)

enter image description here

A way to get the normals from this answer is not so simple, but closed surfaces even when their equations are unknown.

mesh = BoundaryDiscretizeGraphics[foo];
Graphics3D[
 GraphicsComplex[
  MeshCoordinates[mesh],
  {First[
    "DefaultPlotStyle" /. (Method /. 
       Charting`ResolvePlotTheme[Automatic, RegionPlot3D])],
   EdgeForm[], Thread[MeshCells[mesh, 2], Polygon]}, 
  VertexNormals -> Region`Mesh`MeshCellNormals[mesh, 0]
  ]
 ]

enter image description here

Update 2

This does a better job than ListContourPlot3D, but I thought it was basically equivalent to it. It makes the OP's issue seem like a bug in ListContourPlot3D:

ifn = ListInterpolation[Table[x^2 + y^2 + z^2,
    {x, -1, 1, 0.02}, {y, -1, 1, 0.02}, {z, -1, 1, 0.02}]];
ContourPlot3D[ifn[x, y, z], {x, 1, 101}, {y, 1, 101}, {z, 1, 101}, 
 Contours -> {1}, Mesh -> None]

enter image description here

$\endgroup$
2
  • $\begingroup$ Thank you so much, Michael E2. The GraphicsComplex replacement stuff works like a magic. But forgive my slow mind, I do not quite understand what is going on in this replacement, why it works? And what do you mean by "For real data, it seems unusual to know how calculate exactly the normals." I tried x^2 + y^2 - z^2, also works great. Why doesn't mathematica take this procedure into standard ListContourPlot3D? It seems unreasonable to me that ListContourPlot3D can not produce a simple sphere well. $\endgroup$
    – matheorem
    Commented Sep 20, 2021 at 8:21
  • $\begingroup$ @matheorem The replacement sets the VertexNormals to the surface normals calculated from the formula, which is simple for a sphere. ListContourPlot3D does not know the equation x^2 + y^2 + z^2. Most data does not come from known symbolic equations. When the equation is known, ContourPlot3D is the normal choice and uses the procedure. You might report it to WRI to see if they want to look into whether it's a bug or just unavoidable numerical noise. $\endgroup$
    – Michael E2
    Commented Sep 20, 2021 at 12:50

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.