bindings/python/dionysus/viewer/complex3d.py
author Dmitriy Morozov <dmitriy@mrzv.org>
Mon, 06 Mar 2023 12:54:27 -0800
changeset 302 47512d24f907
parent 269 86a02dac0db2
permissions -rw-r--r--
Fix doc/conf.py

from    PyQt4       import QtGui, QtCore
from    PyGLWidget  import PyGLWidget
from    OpenGL.GL   import *
from    dionysus    import Simplex
from    math        import sqrt

class ComplexViewer3D(PyGLWidget):
    def __init__(self, points, complex = None, values = None, subcomplex = None, point_size = 3.):
        self.display_list = None
        PyGLWidget.__init__(self)

        #glEnable( GL_BLEND )
        #glEnable( GL_LINE_SMOOTH )
        #glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        self.point_size = point_size
        self.points = points
        if complex:
            self.complex = [s for s in complex]
        else:
            # Create vertex simplices if no complex provided
            self.complex = [Simplex([i]) for i in xrange(len(self.points))]

        if subcomplex:
            self.subcomplex = subcomplex
        else:
            self.subcomplex = []

        self.values = values
        if not values:
            self.values = [0]*len(self.points)
        self.maxval, self.minval = max(self.values), min(self.values)

        center, radius = self.center_radius()
        self.set_radius(radius)
        self.set_center(center)

        self.make_display_list()

    def center_radius(self):
        c = [0,0,0]
        for p in self.points:
            for i in xrange(3): c[i] += p[i]
        for i in xrange(3): c[i] /= len(self.points)

        r = 0
        for p in self.points:
            d = sqrt((p[0] - c[0])**2 + (p[1] - c[1])**2 + (p[2] - c[2])**2)
            if d > r: r = d
        return c,r

    def paintGL(self):
        PyGLWidget.paintGL(self)
        if self.display_list:
            glCallList(self.display_list)

    def make_display_list(self):
        self.display_list = glGenLists(1)
        glNewList(self.display_list, GL_COMPILE)
        self.draw_complex(self.complex,    self.point_size,   2., self.colormap)
        self.draw_complex(self.subcomplex, 2*self.point_size, 4., colormap = lambda v: (0,1.,0), line_color = (0,1.,0))
        glEndList()


    def draw_complex(self, complex, point_size, line_size, colormap, line_color = (0,0,1.)):
        glPointSize(point_size)
        glLineWidth(line_size)
        complex.sort(lambda s1, s2: -cmp(s1.dimension(), s2.dimension()))
        for s in complex:
            vertices = [v for v in s.vertices]
            if s.dimension() == 0:              # point
                p = self.points[vertices[0]]
                v = self.values[vertices[0]]

                c = self.colormap(v)
                glColor3f(*c)
                glBegin(GL_POINTS)
                glVertex3f(p[0],p[1],p[2])
                glEnd()
            if s.dimension() == 1:            # edge
                p0 = self.points[vertices[0]]
                p1 = self.points[vertices[1]]

                glColor3f(*line_color)
                glBegin(GL_LINES)
                glVertex3f(p0[0],p0[1],p0[2])
                glVertex3f(p1[0],p1[1],p1[2])
                glEnd()
            elif s.dimension() == 2:
                p0 = self.points[vertices[0]]
                p1 = self.points[vertices[1]]
                p2 = self.points[vertices[2]]

                glColor3f(1,1,0)
                glBegin(GL_TRIANGLES)
                glVertex3f(p0[0],p0[1],p0[2])
                glVertex3f(p1[0],p1[1],p1[2])
                glVertex3f(p2[0],p2[1],p2[2])
                glEnd()

    def colormap(self, v):
        if self.maxval <= self.minval:
            t = 0
        else:
            t = (v - self.minval)/(self.maxval - self.minval)
        c = QtGui.QColor()
        c.setHsv(int(t*255), 255, 255)
        cr = float(c.red())/255
        cg = float(c.green())/255
        cb = float(c.blue())/255
        return (cr,cg,cb)

def show_complex_3D(points, complex = None, values = None, subcomplex = None, app = None, point_size = 3.):
    #app = QtGui.QApplication([])
    view = ComplexViewer3D(points, complex, values, subcomplex, point_size)
    view.show()
    view.raise_()
    app.exec_()