Point viewing with color selection
authorDmitriy Morozov <dmitriy@mrzv.org>
Sat, 05 Mar 2011 14:59:46 -0800
changeset 1 da08d9c69f4b
parent 0 f591c821bbc4
child 2 56a5778c903c
Point viewing with color selection
Makefile
PyVEFViewer.py
VEFViewer.py
ViewerItem.py
points.py
viewerInterface.ui
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Sat Mar 05 14:59:46 2011 -0800
@@ -0,0 +1,2 @@
+ui_PyVEFViewer.py: viewerInterface.ui
+	pyuic4 $< > $@
--- a/PyVEFViewer.py	Thu Mar 03 12:58:47 2011 -0800
+++ b/PyVEFViewer.py	Sat Mar 05 14:59:46 2011 -0800
@@ -1,26 +1,26 @@
-#!/usr/bin/env python2
-
-from    PyQt4.QtGui     import *
 from    PyQGLViewer     import *
+from    PyQt4           import QtGui, QtCore
 import  OpenGL.GL as ogl
 
 from    points          import Points, centerMinMax, reduceCMM
-from    opster          import command, dispatch
 
 
 class VEFViewer(QGLViewer):
-    def __init__(self):
-        QGLViewer.__init__(self)
+    def __init__(self, parent = None):
+        super(VEFViewer, self).__init__(parent)
         self.setStateFileName('.PyVEFViewer.xml')
-        self.models = []
+
+    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:
+        for mod in self.models():
             mod.draw()
 
     def drawWithNames(self):
-        for i,mod in enumerate(self.models):
+        for i,mod in enumerate(self.models()):
             mod.drawWithNames(i)
 
     def lights(self):
@@ -34,12 +34,20 @@
         light_spot_dir1 = (camera_dir.x, camera_dir.y, camera_dir.z);
         ogl.glLightfv(ogl.GL_LIGHT1, ogl.GL_POSITION, light_pos1);
 
+    def modelsContextMenu(self, position):
+        item = self.model_list.itemAt(position)
+        if item:
+            item.contextMenu(self.model_list.mapToGlobal(position))
+
+    def modelDoubleClicked(self, item):
+        item.toggleVisible()
+        self.updateGL()
 
     def init(self):
         # ogl.glMaterialf(ogl.GL_FRONT_AND_BACK, ogl.GL_SHININESS, 50.0)
         # specular_color = [ 0.8, 0.8, 0.8, 1.0 ]
         # ogl.glMaterialfv(ogl.GL_FRONT_AND_BACK, ogl.GL_SPECULAR,  specular_color)
-        self.restoreStateFromFile()
+        # self.restoreStateFromFile()
         # self.help()
 
         ogl.glShadeModel(ogl.GL_SMOOTH);
@@ -57,31 +65,24 @@
 
     def read_points(self, points):
         for pts in points:
-            self.models.append(Points(pts))
+            self.model_list.addItem(Points(pts, self.model_list))
+    def read_edges(self, edges):
+        pass
+    def read_triangles(self, triangles):
+        pass
+
+    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.centerScene()
+        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))
-
-    def centerScene(self):
-        self.center, self.min, self.max = reduceCMM((mod.center, mod.min, mod.max) for mod in self.models)
+        self.setSceneCenter(Vec(self.center.x, self.center.y, self.center.z))
 
-@command(usage = '%name [options]')
-def main(points     = ('p', [], 'files with points'),       # TODO: add completer for filenames
-         edges      = ('e', [], 'files with edges'),
-         triangles  = ('t', [], 'files with triangles')):
-    qapp = QApplication([])
-    viewer = VEFViewer()
-    viewer.setWindowTitle("PyVEFViewer")
-    viewer.show()
-
-    viewer.read_points(points)
-    #viewer.read_edges(edges)
-    #viewer.read_triangles(triangles)
-    viewer.normalize_view()
-
-    qapp.exec_()
-
-if __name__ == '__main__':
-    main()
+    def scene_parameters(self):
+        self.center, self.min, self.max = reduceCMM((mod.center, mod.min, mod.max) for mod in self.models())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VEFViewer.py	Sat Mar 05 14:59:46 2011 -0800
@@ -0,0 +1,31 @@
+#!/usr/bin/env python2
+
+import  ui_PyVEFViewer  as ui
+from    opster          import command, dispatch
+
+class VEFViewerWindow(ui.QtGui.QDialog):
+    def __init__(self, parent = None):
+        super(VEFViewerWindow, self).__init__(parent)
+
+        self.ui = ui.Ui_Dialog()
+        self.ui.setupUi(self)
+
+@command(usage = '%name [options]')
+def main(points     = ('p', [], 'files with points'),       # TODO: add completer for filenames
+         edges      = ('e', [], 'files with edges'),
+         triangles  = ('t', [], 'files with triangles')):
+    
+    qapp = ui.QtGui.QApplication([])
+    win  = VEFViewerWindow()
+    win.show()
+
+    win.ui.viewer.set_list(win.ui.modelList)
+    win.ui.viewer.read_points(points)
+    win.ui.viewer.read_edges(edges)
+    win.ui.viewer.read_triangles(triangles)
+    win.ui.viewer.normalize_view()
+
+    qapp.exec_()
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ViewerItem.py	Sat Mar 05 14:59:46 2011 -0800
@@ -0,0 +1,18 @@
+from    PyQt4       import QtGui, QtCore 
+
+class ViewerItem(QtGui.QListWidgetItem):
+    def __init__(self, name, parent = None):
+        super(ViewerItem, self).__init__(name, parent, QtGui.QListWidgetItem.UserType)
+
+    def toggleVisible(self):
+        self.visible = not self.visible
+        self.setChecked()
+
+    def setChecked(self):
+        if self.visible:
+            self.setCheckState(QtCore.Qt.Checked)
+        else:
+            self.setCheckState(QtCore.Qt.Unchecked)
+    
+    def contextMenu(self, position):
+        pass
--- a/points.py	Thu Mar 03 12:58:47 2011 -0800
+++ b/points.py	Sat Mar 05 14:59:46 2011 -0800
@@ -1,7 +1,8 @@
 from    OpenGL.GL   import glGenLists, glNewList, GL_COMPILE, glEndList, glCallList, \
                            glBegin, glEnd, GL_POINTS, glVertex3f, glColor3f, \
                            glEnable, glDisable, GL_LIGHTING
-
+from    PyQt4       import QtGui, QtCore
+from    ViewerItem  import ViewerItem
 
 class Point(object):
     __slots__ = ('x','y','z')
@@ -33,15 +34,19 @@
         return Point((max(self.x, p.x), max(self.y, p.y), max(self.z, p.z)))
 
 
-class Points(object):
-    def __init__(self, filename):
+class Points(ViewerItem):
+    def __init__(self, filename, parent = None):
+        super(Points, self).__init__(filename, parent)
+
         self.points = []
         with open(filename) as f:
             for line in f:
                 if line.startswith('#'): continue
                 self.points.append(Point(map(float, line.split())))
         self.create_display_list()
-        self.color = (255, 0, 255)
+        self.color = QtGui.QColor(255, 0, 255)
+        self.visible = True
+        self.setChecked()
         self.center, self.min, self.max = centerMinMax(self.points)
 
     def create_display_list(self):
@@ -53,8 +58,18 @@
         glEnd()
         glEndList()
 
+    def contextMenu(self, position):
+        menu = QtGui.QMenu()
+        colorAction = menu.addAction("Color")
+        action = menu.exec_(position)
+        if action == colorAction:
+            color = QtGui.QColorDialog.getColor(self.color)
+            if color.isValid():
+                self.color = color
+
     def draw(self):
-        r,g,b = self.color
+        if not self.visible: return
+        r,g,b,a = self.color.getRgb()
         glColor3f(r,g,b)
         glDisable(GL_LIGHTING)
         glCallList(self.display_list)
@@ -71,7 +86,7 @@
         center += p
         min = p.min(min)
         max = p.max(max)
-    center /= count        
+    if count: center /= count        
 
     return center, min, max
 
@@ -83,6 +98,6 @@
         center += c
         min_ = min.min(min_)
         max_ = max.max(max_)
-    center /= count
+    if count: center /= count
 
-    return center, min, max
+    return center, min_, max_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/viewerInterface.ui	Sat Mar 05 14:59:46 2011 -0800
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>945</width>
+    <height>667</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>PyVEFViewer</string>
+  </property>
+  <layout class="QVBoxLayout">
+   <property name="spacing">
+    <number>6</number>
+   </property>
+   <property name="margin">
+    <number>9</number>
+   </property>
+   <item>
+    <widget class="QSplitter" name="splitter">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <widget class="QListWidget" name="modelList">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="contextMenuPolicy">
+       <enum>Qt::CustomContextMenu</enum>
+      </property>
+     </widget>
+     <widget class="VEFViewer" name="viewer" native="true">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>VEFViewer</class>
+   <extends>QWidget</extends>
+   <header>PyVEFViewer</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>