This is a read-only mirror of pymolwiki.org

Ellipsoid

From PyMOL Wiki
Revision as of 22:03, 11 July 2005 by Gilleain (talk | contribs)
Jump to navigation Jump to search

This script provides a class called "SimpleEllipsoid" that can be created and loaded into pymol as a callback object. It uses code that is ported from this c++ code and seems to be correct! In theory, this could be extended to make toroidal objects, as well as cylinders, spheres, and 'pillows'. Probably not very useful, though.

Here is the script. The last four lines show this in use, by making two ellipses and loading them into pymol.

from pymol.opengl.gl import *
from pymol.callback import Callback
from pymol import cmd

def signOfFloat(f):
        if f < 0: return -1
        if f > 0: return 1
        return 0

def sqC(v, n):
        return signOfFloat(math.cos(v)) *  math.pow(math.fabs(math.cos(v)), n)

def sqCT(v, n, alpha):
        return alpha + sqC(v, n)

def sqS(v, n):
        return signOfFloat(math.sin(v)) * math.pow(math.fabs(math.sin(v)), n)

def sqEllipsoid(a1, a2, a3, u, v, n, e):
        x = a1 * sqC(u, n) * sqC(v, e)
        y = a2 * sqC(u, n) * sqS(v, e)
        z = a3 * sqS(u, n)
        nx = sqC(u, 2 - n) * sqC(v, 2 - e) / a1
        ny = sqC(u, 2 - n) * sqS(v, 2 - e) / a2
        nz = sqS(u, 2 - n) / a3
        return x, y, z, nx, ny, nz

def sqToroid(a1, a2, a3, u, v, n, e, alpha):
        a1prime = 1 / (a1 + alpha)
        a2prime = 1 / (a2 + alpha)
        a3prime = 1 / (a3 + alpha)
        x = a1prime * sqCT(u, e, alpha) * sqC(v, n)
        y = a2prime * sqCT(u, e, alpha) * sqS(v, n)
        z = a3prime * sqS(u, e)
        nx = sqC(u, 2 - e) * sqC(v, 2 - n) / a1prime
        ny = sqC(u, 2 - e) * sqS(v, 2 - n) / a2prime
        nz = sqS(u, 2 - e) / a3prime
        return x, y, z, nx, ny, nz

class SuperQuadricEllipsoid(Callback):

        def __init__(self, x, y, z, a1, a2, a3, n, e, u1, u2, v1, v2, u_segs, v_segs, alpha=0):

                # Calculate delta variables
                dU = (u2 - u1) / u_segs
                dV = (v2 - v1) / v_segs

                # Setup storage for data
                self.points = []
                self.normals = []

                # Store the position
                self.x, self.y, self.z = x, y, z

                # Initialize variables for loop
                U = u1
                for Y in range(0, u_segs):
                        # Initialize variables for loop
                        V = v1
                        for X in range(0, v_segs):
                                # VERTEX #1 */
                                x, y, z, nx, ny, nz = sqEllipsoid(a1, a2, a3, U, V, n, e)
                                self.points.append((x, y, z))
                                self.normals.append((nx, ny, nz))

                                # VERTEX #2 */     
                                x, y, z, nx, ny, nz = sqEllipsoid(a1, a2, a3, U + dU, V, n, e)
                                self.points.append((x, y, z))
                                self.normals.append((nx, ny, nz))

                                # VERTEX #3 */
                                x, y, z, nx, ny, nz = sqEllipsoid(a1, a2, a3, U + dU, V + dV, n, e)
                                self.points.append((x, y, z))
                                self.normals.append((nx, ny, nz))

                                # VERTEX #4 */
                                x, y, z, nx, ny, nz = sqEllipsoid(a1, a2, a3, U, V + dV, n, e)
                                self.points.append((x, y, z))
                                self.normals.append((nx, ny, nz))

                                # Update variables for next loop */
                                V += dV
                        # Update variables for next loop */
                        U += dU

        def get_extent(self):
                return [[-10.0, -10.0, -10.0], [10.0, 10.0, 10.0]]

        def __call__(self):
                glPushMatrix()
                glTranslatef(self.x, self.y, self.z)
                glBegin(GL_QUADS)
                glColor3f(1.0, 1.0, 0.0)
                for i in range(0, u_segs * v_segs * 4):
                        x, y, z = self.points[i]
                        nx, ny, nz = self.normals[i]
                        glNormal3f(nx, ny, nz)
                        glVertex3f(x, y, z)
                glEnd()
                glPopMatrix()

class SimpleEllipsoid(SuperQuadricEllipsoid):

        def __init__(self, x, y, z, a1, a2, a3):
                SuperQuadricEllipsoid.__init__(self, x, y, z, a1, a2, a3, 1.0, 1.0, -math.pi / 2, math.pi / 2, -math.pi, math.pi, 10, 10)

x, y, z = 1, 1, 1
rx, ry, rz = 1, 2, 3
cmd.load_callback(SimpleEllipsoid(x, y, z, rx, ry, rz), 'ellipsoid1')
x, y, z = 2, 2, 2
rx, ry, rz = 2, 1, 3
cmd.load_callback(SimpleEllipsoid(x, y, z, rx, ry, rz), 'ellipsoid2')