PyVEFViewer.py
author Dmitriy Morozov <dmitriy@mrzv.org>
Tue, 21 Jun 2011 16:48:36 -0700
changeset 18 7d5e8fdf69f2
parent 16 69f6b439b161
child 19 c1c2dda0c427
permissions -rw-r--r--
Pipe radius is centralized in edges.py

from    PyQGLViewer     import *
from    PyQt4           import QtGui, QtCore
import  OpenGL.GL as ogl
from    os.path         import splitext; ext = lambda fn: splitext(fn)[1]

from    points          import Points, centerMinMax, reduceCMM
from    edges           import Edges
from    triangles       import Triangles
from    spheres         import Spheres
import  povray


class VEFViewer(QGLViewer):
    def __init__(self, parent = None):
        super(VEFViewer, self).__init__(parent)
        self.setStateFileName('.PyVEFViewer.xml')

    def models(self):
        for i in xrange(self.model_list.count()):
            yield self.model_list.item(i)

    def draw(self):
        self.lights()
        for mod in self.models():
            mod.draw()

    def drawWithNames(self):
        for i,mod in enumerate(self.models()):
            mod.drawWithNames(i)

    def lights(self):
        # Place light at camera position
        cameraPos = self.camera().position()
        pos = [cameraPos[0], cameraPos[1], cameraPos[2], 1.0]
        ogl.glLightfv(ogl.GL_LIGHT1, ogl.GL_POSITION, pos)

    def modelsContextMenu(self, position):
        item = self.model_list.itemAt(position)
        if item:
            item.contextMenu(self.model_list.mapToGlobal(position))
        self.updateGL()

    def modelDoubleClicked(self, item):
        item.toggleVisible()
        self.updateGL()

    def keyPressEvent(self, e):
        if e.key() == QtCore.Qt.Key_O:
            filename = QtGui.QFileDialog.getOpenFileName(self, 'Open file')
            self.read_from_extension(str(filename))
            self.normalize_view()
        elif e.key() == QtCore.Qt.Key_P:
            if self.camera().type() == Camera.ORTHOGRAPHIC:
                self.camera().setType(Camera.PERSPECTIVE)
            else:
                self.camera().setType(Camera.ORTHOGRAPHIC)
            self.updateGL()
        elif e.key() == QtCore.Qt.Key_S:
            self.save_povray()
        else:
            super(VEFViewer, self).keyPressEvent(e)

    def init(self):
        # Light setup
        ogl.glDisable(ogl.GL_LIGHT0);
        ogl.glEnable(ogl.GL_LIGHT1);

        # Light default parameters
        light_ambient  = [1.0, 1.0, 1.0, 1.0]
        light_specular = [1.0, 1.0, 1.0, 1.0]
        light_diffuse  = [1.0, 1.0, 1.0, 1.0]

        ogl.glLightf( ogl.GL_LIGHT1, ogl.GL_SPOT_EXPONENT, 3.0)
        ogl.glLightf( ogl.GL_LIGHT1, ogl.GL_SPOT_CUTOFF,   10.0)
        ogl.glLightf( ogl.GL_LIGHT1, ogl.GL_CONSTANT_ATTENUATION,  0.1)
        ogl.glLightf( ogl.GL_LIGHT1, ogl.GL_LINEAR_ATTENUATION,    0.3)
        ogl.glLightf( ogl.GL_LIGHT1, ogl.GL_QUADRATIC_ATTENUATION, 0.3)
        ogl.glLightfv(ogl.GL_LIGHT1, ogl.GL_AMBIENT,  light_ambient)
        ogl.glLightfv(ogl.GL_LIGHT1, ogl.GL_SPECULAR, light_specular)
        ogl.glLightfv(ogl.GL_LIGHT1, ogl.GL_DIFFUSE,  light_diffuse)


    #def helpString(self):
    #    return helpstr

    def save_povray(self):
        filename = QtGui.QFileDialog.getSaveFileName(self, 'Save POV-Ray file', '.', 'POV-Ray files (*.pov)')
        if not filename: return

        pos = self.camera().position()
        dir = self.camera().viewDirection()
        up  = self.camera().upVector()
        right  = self.camera().rightVector()
        at  = pos + dir

        with open(filename, 'w') as f:
            f.write('#include "colors.inc"\n')
            f.write('background { rgb 1 }\n')
            f.write(povray.camera(pos, at))
            f.write(povray.spotlight(pos, at))

            for m in self.models():
                if m.visible: m.save_povray(f)

    def read_points(self, points):
        for pts in points:
            self.model_list.addItem(Points(pts, self.model_list))

    def read_edges(self, edges):
        for edg in edges:
            self.model_list.addItem(Edges(edg, self.model_list))

    def read_triangles(self, triangles):
        for tri in triangles:
            self.model_list.addItem(Triangles(tri, self.model_list))

    def read_spheres(self, spheres):
        for sph in spheres:
            self.model_list.addItem(Spheres(sph, self.model_list))

    def read_from_extension(self, fn):
        if   ext(fn) == '.vrt' or ext(fn) == '.pts':
            self.read_points([fn])
        elif ext(fn) == '.edg':
            self.read_edges([fn])
        elif ext(fn) == '.stl':
            self.read_triangles([fn])
        elif ext(fn) == '.sph':
            self.read_spheres([fn])
        else:
            return False

        return True

    def set_list(self, model_list):
        self.model_list = model_list
        self.model_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.model_list.customContextMenuRequested.connect(self.modelsContextMenu)
        self.model_list.itemDoubleClicked.connect(self.modelDoubleClicked)

    def normalize_view(self):
        self.scene_parameters()

        self.setSceneBoundingBox(Vec(self.min.x, self.min.y, self.min.z), \
                                 Vec(self.max.x, self.max.y, self.max.z))
        self.setSceneCenter(Vec(self.center.x, self.center.y, self.center.z))

    def show_entire_scene(self):
        self.camera().showEntireScene()

    def scene_parameters(self):
        self.center, self.min, self.max = reduceCMM((mod.center, mod.min, mod.max) for mod in self.models())