19

Try to evaluate the following code:

ContourPlot3D[(x^2 + 9/4 y^2 + z^2 - 1)^3 == x^2 z^3 + 9/80 y^2 z^3, 
  {x, -6/5, 6/5}, {y, -6/5, 6/5}, {z, -6/5, 3/2}, 
  Mesh -> None, Boxed -> False, AxesLabel -> {"x", "y", "z"}, 
  PlotPoints -> 50, Axes -> False, 
  ContourStyle -> Directive[Red, Opacity[0.58], Specularity[Yellow, 30]], 
  AspectRatio -> 1.15, ViewPoint ->{-0.930, -3.137, -0.860}]

The resulted heart looks broken:

enter image description here

Increase the PlotPoints value to up to 200 improves the appearance but does not solve it.

What is happening?

rm -rf
  • 88,781
  • 21
  • 293
  • 472
LCFactorization
  • 3,047
  • 24
  • 37

1 Answers1

25

Taking the cube root on both sides fixes the problem, and then you don't need lots of PlotPoints any more.

ContourPlot3D[(x^2 + 9/4 y^2 + z^2 - 1) == CubeRoot[x^2 z^3 + 9/80 y^2 z^3], 
{x, -6/5, 6/5}, {y, -6/5, 6/5}, {z, -6/5, 3/2}, Mesh -> None, Boxed -> False, 
 AxesLabel -> {"x", "y", "z"}, Axes -> False, 
 ContourStyle -> Directive[Red, Opacity[0.58], Specularity[Yellow, 30]], 
 AspectRatio -> 1.15, ViewPoint -> {-0.930, -3.137, -0.860}]

enter image description here

As Algohi pointed out, the problem only occurs at $z = 0$, at which the original equation becomes

(x^2 + 9/4 y^2 + z^2 - 1)^3 == x^2 z^3 + 9/80 y^2 z^3 /. z -> 0
(-1 + x^2 + (9 y^2)/4)^3 == 0

Here every zero crossing is a critical point: the function doesn't cross zero briskly like most functions do, it lingers in the neighbourhood because its derivative is zero as well. Since the ContourPlot functions find the zero crossings numerically, they have a hard time getting the location exactly right. Take your favourite ContourPlot of any function $f(x,y)=0$ and try plotting $f(x,y)^3=0$ instead, and you'll see what happens. (Though if you plot $f(x,y)^2=0$ you might not see anything at all.)