Search code examples
pythonplot3dmayavi

Mayavi combining two implicit 3d surfaces


I use Mayavi to plot implicit 3d surfaces and I would like to combine those surfaces into one plot. However, when I do this I get something similar like this:

enter image description here

The code I am using:

import numpy as np
from mayavi import mlab

A=0.24639243776
B=5.39100472027e-17
C=1.71555149594
D=1.72967325617
E=7.50535440036
F=-1.17072847143
G=1.0

x, y, z = np.ogrid[-3:1:100j, -10:1:100j, 0:3:100j]

def Fun (x,y,z, A,B,C,D,E,F,G):
    F1 = (x - A + y - B) / 2 + np.sqrt(((x - A - y + B) / 2) ** 2 + C * z ** 2)
    F2 = np.sqrt(x*((F*y)/2 + (E*x)/D) + y*((F*x)/2 + (D*y)/E) + G*z**2) - np.sqrt(D*E)
    F1 [F1 < 0] = F2 [F1 < 0]
    return F1

Fu = Fun (x,y,z,A,B,C,D,E,F,G)

mlab.contour3d(Fu, contours = [0])
mlab.show()

The problem is that no matter how I do it one of the surfaces is very low poly! I had plotted the same in Mathematica and it produces a perfect plot:

enter image description here

I do not expect to get the same quality plot as Mathematica is a commercial product. But at least I would like for both surfaces to be smooth.

If Mayavi is not the right tool for the task, maybe you could recommend something different with which I could achieve the desired result.

Thanks in advance!


Solution

  • I figured it out. The key is to set the surface to None for it to be trimmed. Then the other surface can be drawn in the same fashion. Furthermore for the surface to be plotted according to scale, x,y,z has to be also passed into the contour3d

    import numpy as np
    from mayavi import mlab
    
    A=0.24639243776
    B=5.39100472027e-17
    C=1.71555149594
    D=1.72967325617
    E=7.50535440036
    F=-1.17072847143
    G=1.0
    
    x, y, z = np.mgrid[-3:1:300j, -10:1:300j, 0:3:300j]
    
    def Fun1 (x,y,z, A,B,C,D,E,F,G):
        F1 = (x - A + y - B) / 2 + np.sqrt(((x - A - y + B) / 2) ** 2 + C * z ** 2)
        F2 = np.sqrt(x*((F*y)/2 + (E*x)/D) + y*((F*x)/2 + (D*y)/E) + G*z**2) - np.sqrt(D*E)
        F1 [F2 > 0.0] = None
        return F1
    
    
    def Fun2 (x,y,z, A,B,C,D,E,F,G):
        F1 = (x - A + y - B) / 2 + np.sqrt(((x - A - y + B) / 2) ** 2 + C * z ** 2)
        F2 = np.sqrt(x*((F*y)/2 + (E*x)/D) + y*((F*x)/2 + (D*y)/E) + G*z**2) - np.sqrt(D*E)
        F2 [F1 > 0.0] = None
        return F2
    
    Fu1 = Fun1 (x,y,z,A,B,C,D,E,F,G)
    Fu2 = Fun2 (x,y,z,A,B,C,D,E,F,G)
    
    mlab.contour3d(x,y,z,Fu1, contours = [0])
    mlab.contour3d(x,y,z,Fu2, contours = [0])
    mlab.show()
    

    And here is the result:

    enter image description here