Changeset 8395:c451188fe0c3 in orange


Ignore:
Timestamp:
07/18/11 22:38:43 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
37e5c0ce6df799c46370460799709d23c4beadd7
Message:

owplot3d: selections

Location:
orange/OrangeWidgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Prototypes/OWScatterPlot3D.py

    r8391 r8395  
    1515  
    1616    def __init__(self, parent=None, signalManager=None, name="Scatter Plot 3D"): 
    17         OWWidget.__init__(self, parent, signalManager, name) 
     17        OWWidget.__init__(self, parent, signalManager, name, True) 
    1818 
    1919        self.inputs = [("Examples", ExampleTable, self.setData), ("Subset Examples", ExampleTable, self.setSubsetData)] 
    20         self.outputs = [] 
     20        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable)] 
    2121 
    2222        self.x_attr = 0 
     
    108108 
    109109        self.mainArea.layout().addWidget(self.plot) 
     110        self.connect(self.graphButton, SIGNAL("clicked()"), self.plot.save_to_file) 
     111 
     112        self.plot.auto_send_selection_callback = self.send_selections 
    110113 
    111114        self.data = None 
     
    163166    def handleNewSignals(self): 
    164167        self.update_plot() 
     168        self.send_selections() 
     169 
     170    def send_selections(self): 
     171        if self.data == None: 
     172            return 
     173        indices = self.plot.get_selection_indices() 
     174        selected = [1 if i in indices else 0 for i in range(len(self.data))] 
     175        unselected = map(lambda n: 1-n, selected) 
     176        selected = self.data.selectref(selected) 
     177        unselected = self.data.selectref(unselected) 
     178        self.send('Selected Examples', selected) 
     179        self.send('Unselected Examples', unselected) 
    165180 
    166181    def on_axis_change(self): 
  • orange/OrangeWidgets/owplot3d.py

    r8394 r8395  
    4343from PyQt4.QtGui import * 
    4444from PyQt4 import QtOpenGL 
     45from OWDlgs import OWChooseImageSizeDlg 
    4546 
    4647import orange 
     
    9697glBindBuffer = gl.glBindBuffer 
    9798glBufferData = gl.glBufferData 
     99glGenFramebuffers = gl.glGenFramebuffers 
     100glBindFramebuffer = gl.glBindFramebuffer 
     101glFramebufferTexture2D = gl.glFramebufferTexture2D 
     102glCheckFramebufferStatus = gl.glCheckFramebufferStatus 
     103glGenTextures = gl.glGenTextures 
     104GL_FRAMEBUFFER_COMPLETE = 0x8CD5 
     105GL_FRAMEBUFFER = 0x8D40 
     106GL_COLOR_ATTACHMENT0 = 0x8CE0 
    98107 
    99108 
     
    163172        ''' 
    164173        if not Symbol.is_valid(symbol): 
     174            print('Legend: invalid symbol') 
    165175            return 
    166176        self.items.append([symbol, color, size, title]) 
     
    286296 
    287297        self.build_axes() 
     298        self.selections = [] 
     299        self.auto_send_selection_callback = None 
    288300 
    289301    def __del__(self): 
     
    400412        if not linked.value: 
    401413            print('Failed to link shader!') 
    402         print('Shaders compiled and linked!') 
     414        else: 
     415            print('Shaders compiled and linked!') 
     416 
     417        # Create Framebuffer object, which will be render target for axes values and titles. 
     418        self.auxiliary_fbo = QtOpenGL.QGLFramebufferObject(1024, 1024) 
     419        if self.auxiliary_fbo.isValid(): 
     420            print('Auxiliary fbo created!') 
     421        else: 
     422            print('Failed to create auxiliary fbo!') 
    403423 
    404424    def resizeGL(self, width, height): 
     
    406426 
    407427    def paintGL(self): 
     428 
    408429        glClearColor(1,1,1,1) 
    409430        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
     
    471492            self.legend.draw() 
    472493 
     494        #self.draw_labels_and_titles_to_fbo() 
    473495        self.draw_helpers() 
    474496 
     
    494516                            'Scale {0} axis'.format(['z', 'x'][self.scale_x_axis]), 
    495517                            font=self.labels_font) 
    496         elif self.state == PlotState.SELECTING: 
     518        elif self.state == PlotState.SELECTING and self.new_selection[3] != None: 
    497519            s = self.new_selection 
    498520            glColor4f(0, 0, 0, 1) 
     
    501523            draw_line(s[2], s[3], s[2], s[1]) 
    502524            draw_line(s[2], s[1], s[0], s[1]) 
     525 
     526        for s in self.selections: 
     527            glColor4f(0, 0, 0, 1) 
     528            draw_line(s[0], s[1], s[0], s[3]) 
     529            draw_line(s[0], s[3], s[2], s[3]) 
     530            draw_line(s[2], s[3], s[2], s[1]) 
     531            draw_line(s[2], s[1], s[0], s[1]) 
     532 
     533        #glEnable(GL_TEXTURE_2D) 
     534        #glBindTexture(GL_TEXTURE_2D, self.auxiliary_fbo.texture()) 
     535        #glColor4f(1, 1, 1, 1) 
     536        #glBegin(GL_QUADS) 
     537        #glTexCoord2f(0, 0); glVertex2f(10, 10) 
     538        #glTexCoord2f(1, 0); glVertex2f(200, 10) 
     539        #glTexCoord2f(1, 1); glVertex2f(200, 200) 
     540        #glTexCoord2f(0, 1); glVertex2f(10, 200) 
     541        #glEnd() 
     542        #glBindTexture(GL_TEXTURE_2D, 0) 
    503543 
    504544    def set_x_axis_title(self, title): 
     
    664704        self.scale_x_axis = False if rightmost_visible % 2 == 0 else True 
    665705 
     706    def draw_labels_and_titles_to_fbo(self): 
     707        self.auxiliary_fbo.bind() 
     708        #glPushAttrib(GL_VIEWPORT_BIT) 
     709        #glViewport(0, 0, 512, 512) 
     710        glClearColor(1, 1, 1, 1) 
     711        glClear(GL_COLOR_BUFFER_BIT) 
     712        glMatrixMode(GL_PROJECTION) 
     713        glLoadIdentity() 
     714        glOrtho(0, 1024, 1024, 0, -1, 1) 
     715        glMatrixMode(GL_MODELVIEW) 
     716        glLoadIdentity() 
     717        glColor3f(0,0,0) 
     718        self.renderText(10,200, 'Are you talking to me?!') 
     719 
     720        glColor4f(1, 0, 0, 1) 
     721        glBegin(GL_TRIANGLES) 
     722        glVertex2f(10,10) 
     723        glVertex2f(100, 10) 
     724        glVertex2f(80, 200) 
     725        glEnd() 
     726 
     727        #glPopAttrib() 
     728        self.auxiliary_fbo.release() 
     729 
    666730    def build_axes(self): 
    667731        edge_half = self.view_cube_edge / 2. 
     
    718782            symbols = [0 for _ in range(num_points)] 
    719783 
    720         #max, min = numpy.max(array, axis=0), numpy.min(array, axis=0) 
    721784        min = self.min_x, self.min_y, self.min_z = numpy.min(X), numpy.min(Y), numpy.min(Z) 
    722785        max = self.max_x, self.max_y, self.max_z = numpy.max(X), numpy.max(Y), numpy.max(Z) 
     
    813876        self.updateGL() 
    814877 
     878    def save_to_file(self): 
     879        size_dlg = OWChooseImageSizeDlg(self, [], parent=self) 
     880        size_dlg.exec_() 
     881 
     882    def save_to_file_direct(self, file_name): 
     883        pass 
     884 
     885    def get_selection_indices(self): 
     886        if len(self.selections) == 0: 
     887            return [] 
     888 
     889        projection = QMatrix4x4() 
     890        projection.perspective(self.camera_fov, float(self.width())/self.height(), 0.1, 2000) 
     891 
     892        modelview = QMatrix4x4() 
     893        modelview.lookAt(QVector3D(self.camera[0]*self.camera_distance, 
     894                                   self.camera[1]*self.camera_distance, 
     895                                   self.camera[2]*self.camera_distance), 
     896                         QVector3D(0, 0, 0), 
     897                         QVector3D(0, 1, 0)) 
     898 
     899        modelview.scale(*(numpy.maximum([0, 0, 0], self.scale + self.add_scale))) 
     900        modelview.translate(*(-self.center)) 
     901 
     902        proj_model = projection * modelview 
     903        viewport = [0, 0, self.width(), self.height()] 
     904 
     905        def project(x, y, z): 
     906            projected = proj_model * QVector4D(x, y, z, 1) 
     907            projected /= projected.z() 
     908            winx = viewport[0] + (1 + projected.x()) * viewport[2] / 2 
     909            winy = viewport[1] + (1 + projected.y()) * viewport[3] / 2 
     910            winy = self.height() - winy 
     911            return winx, winy 
     912 
     913        def inside_selection(x_win, y_win): 
     914            for selection in self.selections: 
     915                x1, x2 = sorted([selection[0], selection[2]]) 
     916                y1, y2 = sorted([selection[1], selection[3]]) 
     917                if x1 <= x_win <= x2 and\ 
     918                   y1 <= y_win <= y2: 
     919                    return True 
     920            return False 
     921 
     922        indices = [] 
     923        for (cmd, params) in self.commands: 
     924            if cmd == 'scatter': 
     925                _, _, (X, Y, Z), _ = params 
     926                for i, (x, y, z) in enumerate(zip(X, Y, Z)): 
     927                    x_win, y_win = project(x, y, z) 
     928                    if inside_selection(x_win, y_win): 
     929                        indices.append(i) 
     930 
     931        return indices 
     932 
    815933    def mousePressEvent(self, event): 
    816934        pos = self.mouse_pos = event.pos() 
     
    821939            else: 
    822940                self.state = PlotState.SELECTING 
    823                 self.new_selection = [pos.x(), pos.y(), 0, 0] 
     941                self.new_selection = [pos.x(), pos.y(), None, None] 
    824942        elif buttons & Qt.RightButton: 
     943            self.selections = [] 
    825944            self.state = PlotState.SCALING 
    826945            self.scaling_init_pos = self.mouse_pos 
     
    839958                self.new_selection[2:] = [pos.x(), pos.y()] 
    840959        elif event.buttons() & Qt.MiddleButton: 
     960            self.selections = [] 
    841961            if QApplication.keyboardModifiers() & Qt.ShiftModifier: 
    842                 off_x = numpy.cross(self.camera, [0,1,0]) * (dx / self.move_factor) 
     962                off_x = numpy.cross(self.camera, [0, 1, 0]) * (dx / self.move_factor) 
    843963                #off_y = numpy.cross(self.camera, [1,0,0]) * (dy / self.move_factor) 
    844964                # TODO: this incidentally works almost fine, but the math is wrong and should be fixed 
     
    864984    def mouseReleaseEvent(self, event): 
    865985        if self.state == PlotState.SCALING: 
    866             self.scale = numpy.maximum([0,0,0], self.scale + self.add_scale) 
    867             self.add_scale = [0,0,0] 
     986            self.scale = numpy.maximum([0, 0, 0], self.scale + self.add_scale) 
     987            self.add_scale = [0, 0, 0] 
     988        elif self.state == PlotState.SELECTING: 
     989            if self.new_selection[3] != None: 
     990                self.selections.append(self.new_selection) 
     991                self.auto_send_selection_callback() if self.auto_send_selection_callback else None 
    868992 
    869993        self.state = PlotState.IDLE 
     
    872996    def wheelEvent(self, event): 
    873997        if event.orientation() == Qt.Vertical: 
     998            self.selections = [] 
    874999            delta = 1 + event.delta() / self.zoom_factor 
    8751000            self.scale *= delta 
     
    8781003    def clear(self): 
    8791004        self.commands = [] 
     1005        self.selections = [] 
    8801006        self.legend.clear() 
    8811007 
Note: See TracChangeset for help on using the changeset viewer.