Changeset 8927:05c79276351e in orange


Ignore:
Timestamp:
09/08/11 18:19:14 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
f74f1fd176942e057a3ae59190136de57a9aa96c
Message:

Moved axis management to scatterplt

Location:
orange/OrangeWidgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Visualize Qt/OWScatterPlot3D.py

    r8922 r8927  
    55''' 
    66 
     7from math import log10, ceil, floor 
     8 
    79from OWWidget import * 
    810from plot.owplot3d import * 
    911from plot.owtheme import ScatterLightTheme, ScatterDarkTheme 
    1012from plot import OWPoint 
     13from plot.primitives import normalize, normal_from_points 
    1114 
    1215import orange 
     
    1720 
    1821import OWGUI 
    19 import OWToolbars 
    2022import orngVizRank 
    2123from OWkNNOptimization import * 
     
    2527 
    2628TooltipKind = enum('NONE', 'VISIBLE', 'ALL') 
     29Axis = enum('X', 'Y', 'Z') 
     30 
     31def plane_visible(plane, location): 
     32    normal = normal_from_points(*plane[:3]) 
     33    loc_plane = normalize(plane[0] - location) 
     34    if numpy.dot(normal, loc_plane) > 0: 
     35        return False 
     36    return True 
     37 
     38def nicenum(x, round): 
     39    if x <= 0.: 
     40        return x # TODO: what to do in such cases? 
     41    expv = floor(log10(x)) 
     42    f = x / pow(10., expv) 
     43    if round: 
     44        if f < 1.5: nf = 1. 
     45        elif f < 3.: nf = 2. 
     46        elif f < 7.: nf = 5. 
     47        else: nf = 10. 
     48    else: 
     49        if f <= 1.: nf = 1. 
     50        elif f <= 2.: nf = 2. 
     51        elif f <= 5.: nf = 5. 
     52        else: nf = 10. 
     53    return nf * pow(10., expv) 
     54 
     55def loose_label(min_value, max_value, num_ticks): 
     56    '''Algorithm by Paul S. Heckbert (Graphics Gems). 
     57       Generates a list of "nice" values between min and max, 
     58       given the number of ticks. Also returns the number 
     59       of fractional digits to use. 
     60    ''' 
     61    range = nicenum(max_value-min_value, False) 
     62    d = nicenum(range / float(num_ticks-1), True) 
     63    if d <= 0.: # TODO 
     64        return numpy.arange(min_value, max_value, (max_value-min_value)/num_ticks), 1 
     65    plot_min = floor(min_value / d) * d 
     66    plot_max = ceil(max_value / d) * d 
     67    num_frac = int(max(-floor(log10(d)), 0)) 
     68    return numpy.arange(plot_min, plot_max + 0.5*d, d), num_frac 
    2769 
    2870class ScatterPlot(OWPlot3D, orngScaleScatterPlotData): 
     
    3577        self.show_grid = True 
    3678        self.show_chassis = True 
     79        self.show_axes = True 
     80        self.build_axes() 
     81 
     82        self.x_axis_labels = None 
     83        self.y_axis_labels = None 
     84        self.z_axis_labels = None 
     85 
     86        self.x_axis_title = '' 
     87        self.y_axis_title = '' 
     88        self.z_axis_title = '' 
     89 
     90        self.show_x_axis_title = self.show_y_axis_title = self.show_z_axis_title = True 
    3791 
    3892        self.animate_plot = False 
     93 
     94    def set_axis_labels(self, axis_id, labels): 
     95        '''labels should be a list of strings''' 
     96        if Axis.is_valid(axis_id): 
     97            setattr(self, Axis.to_str(axis_id).lower() + '_axis_labels', labels) 
     98 
     99    def set_axis_title(self, axis_id, title): 
     100        if Axis.is_valid(axis_id): 
     101            setattr(self, Axis.to_str(axis_id).lower() + '_axis_title', title) 
     102 
     103    def set_show_axis_title(self, axis_id, show): 
     104        if Axis.is_valid(axis_id): 
     105            setattr(self, 'show_' + Axis.to_str(axis_id).lower() + '_axis_title', show) 
    39106 
    40107    def set_data(self, data, subset_data=None, **args): 
     
    67134           self.data_domain[symbol_attr].varType == Discrete: 
    68135            symbol_index = self.attribute_name_index[symbol_attr] 
    69             symbol_discrete = True 
    70136            num_symbols_used = len(self.data_domain[symbol_attr].values) 
    71137 
     
    111177            data_translation[2] = 1. 
    112178 
     179        self.x_axis_labels = None 
     180        self.y_axis_labels = None 
     181        self.z_axis_labels = None 
     182 
    113183        self.clear() 
    114184 
     
    185255        if self.show_chassis: 
    186256            self.draw_chassis() 
     257        if self.show_axes: 
     258            self.draw_axes() 
    187259 
    188260    def draw_chassis(self): 
     
    273345        glDisable(GL_BLEND) 
    274346 
     347    def build_axes(self): 
     348        edge_half = 1. / 2. 
     349        x_axis = [[-edge_half, -edge_half, -edge_half], [edge_half, -edge_half, -edge_half]] 
     350        y_axis = [[-edge_half, -edge_half, -edge_half], [-edge_half, edge_half, -edge_half]] 
     351        z_axis = [[-edge_half, -edge_half, -edge_half], [-edge_half, -edge_half, edge_half]] 
     352 
     353        self.x_axis = x_axis = numpy.array(x_axis) 
     354        self.y_axis = y_axis = numpy.array(y_axis) 
     355        self.z_axis = z_axis = numpy.array(z_axis) 
     356 
     357        self.unit_x = unit_x = numpy.array([1., 0., 0.]) 
     358        self.unit_y = unit_y = numpy.array([0., 1., 0.]) 
     359        self.unit_z = unit_z = numpy.array([0., 0., 1.]) 
     360  
     361        A = y_axis[1] 
     362        B = y_axis[1] + unit_x 
     363        C = x_axis[1] 
     364        D = x_axis[0] 
     365 
     366        E = A + unit_z 
     367        F = B + unit_z 
     368        G = C + unit_z 
     369        H = D + unit_z 
     370 
     371        self.axis_plane_xy = [A, B, C, D] 
     372        self.axis_plane_yz = [A, D, H, E] 
     373        self.axis_plane_xz = [D, C, G, H] 
     374 
     375        self.axis_plane_xy_back = [H, G, F, E] 
     376        self.axis_plane_yz_right = [B, F, G, C] 
     377        self.axis_plane_xz_top = [E, F, B, A] 
     378 
     379    def draw_axes(self): 
     380        glMatrixMode(GL_PROJECTION) 
     381        glLoadIdentity() 
     382        glMultMatrixd(numpy.array(self.projection.data(), dtype=float)) 
     383        glMatrixMode(GL_MODELVIEW) 
     384        glLoadIdentity() 
     385        glMultMatrixd(numpy.array(self.modelview.data(), dtype=float)) 
     386 
     387        self.renderer.set_transform(self.projection, self.modelview) 
     388 
     389        def draw_axis(line): 
     390            self.qglColor(self._theme.axis_color) 
     391            glLineWidth(2) # TODO: how to draw thick lines? 
     392            glBegin(GL_LINES) 
     393            glVertex3f(*line[0]) 
     394            glVertex3f(*line[1]) 
     395            glEnd() 
     396 
     397        def draw_discrete_axis_values(axis, coord_index, normal, axis_labels): 
     398            start, end = axis.copy() 
     399            start_value = self.map_to_data(start.copy())[coord_index] 
     400            end_value = self.map_to_data(end.copy())[coord_index] 
     401            length = end_value - start_value 
     402            for i, label in enumerate(axis_labels): 
     403                value = (i + 1) * 2 
     404                if start_value <= value <= end_value: 
     405                    position = start + (end-start)*((value-start_value) / length) 
     406                    self.renderer.draw_line( 
     407                        QVector3D(*position), 
     408                        QVector3D(*(position + normal*0.03)), 
     409                        color=self._theme.axis_values_color) 
     410                    position += normal * 0.1 
     411                    self.renderText(position[0], 
     412                                    position[1], 
     413                                    position[2], 
     414                                    label, font=self._theme.labels_font) 
     415 
     416        def draw_values(axis, coord_index, normal, axis_labels): 
     417            glLineWidth(1) 
     418            if axis_labels != None: 
     419                draw_discrete_axis_values(axis, coord_index, normal, axis_labels) 
     420                return 
     421            start, end = axis.copy() 
     422            start_value = self.map_to_data(start.copy())[coord_index] 
     423            end_value = self.map_to_data(end.copy())[coord_index] 
     424            values, num_frac = loose_label(start_value, end_value, 7) 
     425            for value in values: 
     426                if not (start_value <= value <= end_value): 
     427                    continue 
     428                position = start + (end-start)*((value-start_value) / float(end_value-start_value)) 
     429                text = ('%%.%df' % num_frac) % value 
     430                self.renderer.draw_line( 
     431                    QVector3D(*position), 
     432                    QVector3D(*(position+normal*0.03)), 
     433                    color=self._theme.axis_values_color) 
     434                position += normal * 0.1 
     435                self.renderText(position[0], 
     436                                position[1], 
     437                                position[2], 
     438                                text, font=self._theme.axis_font) 
     439 
     440        def draw_axis_title(axis, title, normal): 
     441            middle = (axis[0] + axis[1]) / 2. 
     442            middle += normal * 0.1 if axis[0][1] != axis[1][1] else normal * 0.2 
     443            self.renderText(middle[0], middle[1], middle[2], 
     444                            title, 
     445                            font=self._theme.axis_title_font) 
     446 
     447        glDisable(GL_DEPTH_TEST) 
     448        glLineWidth(1) 
     449        glEnable(GL_BLEND) 
     450        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
     451 
     452        cam_in_space = numpy.array([ 
     453          self.camera[0]*self.camera_distance, 
     454          self.camera[1]*self.camera_distance, 
     455          self.camera[2]*self.camera_distance 
     456        ]) 
     457 
     458        planes = [self.axis_plane_xy, self.axis_plane_yz, 
     459                  self.axis_plane_xy_back, self.axis_plane_yz_right] 
     460        normals = [[numpy.array([0,-1, 0]), numpy.array([-1, 0, 0])], 
     461                   [numpy.array([0, 0,-1]), numpy.array([ 0,-1, 0])], 
     462                   [numpy.array([0,-1, 0]), numpy.array([-1, 0, 0])], 
     463                   [numpy.array([0,-1, 0]), numpy.array([ 0, 0,-1])]] 
     464        visible_planes = [plane_visible(plane, cam_in_space) for plane in planes] 
     465        xz_visible = not plane_visible(self.axis_plane_xz, cam_in_space) 
     466 
     467        if visible_planes[0 if xz_visible else 2]: 
     468            draw_axis(self.x_axis) 
     469            draw_values(self.x_axis, 0, numpy.array([0, 0, -1]), self.x_axis_labels) 
     470            if self.show_x_axis_title: 
     471                draw_axis_title(self.x_axis, self.x_axis_title, numpy.array([0, 0, -1])) 
     472        elif visible_planes[2 if xz_visible else 0]: 
     473            draw_axis(self.x_axis + self.unit_z) 
     474            draw_values(self.x_axis + self.unit_z, 0, numpy.array([0, 0, 1]), self.x_axis_labels) 
     475            if self.show_x_axis_title: 
     476                draw_axis_title(self.x_axis + self.unit_z, 
     477                                self.x_axis_title, numpy.array([0, 0, 1])) 
     478 
     479        if visible_planes[1 if xz_visible else 3]: 
     480            draw_axis(self.z_axis) 
     481            draw_values(self.z_axis, 2, numpy.array([-1, 0, 0]), self.z_axis_labels) 
     482            if self.show_z_axis_title: 
     483                draw_axis_title(self.z_axis, self.z_axis_title, numpy.array([-1, 0, 0])) 
     484        elif visible_planes[3 if xz_visible else 1]: 
     485            draw_axis(self.z_axis + self.unit_x) 
     486            draw_values(self.z_axis + self.unit_x, 2, numpy.array([1, 0, 0]), self.z_axis_labels) 
     487            if self.show_z_axis_title: 
     488                draw_axis_title(self.z_axis + self.unit_x, self.z_axis_title, numpy.array([1, 0, 0])) 
     489 
     490        try: 
     491            rightmost_visible = visible_planes[::-1].index(True) 
     492        except ValueError: 
     493            return 
     494        if rightmost_visible == 0 and visible_planes[0] == True: 
     495            rightmost_visible = 3 
     496        y_axis_translated = [self.y_axis+self.unit_x, 
     497                             self.y_axis+self.unit_x+self.unit_z, 
     498                             self.y_axis+self.unit_z, 
     499                             self.y_axis] 
     500        normals = [numpy.array([1, 0, 0]), 
     501                   numpy.array([0, 0, 1]), 
     502                   numpy.array([-1,0, 0]), 
     503                   numpy.array([0, 0,-1])] 
     504        axis = y_axis_translated[rightmost_visible] 
     505        normal = normals[rightmost_visible] 
     506        draw_axis(axis) 
     507        draw_values(axis, 1, normal, self.y_axis_labels) 
     508        if self.show_y_axis_title: 
     509            draw_axis_title(axis, self.y_axis_title, normal) 
     510 
    275511class OWScatterPlot3D(OWWidget): 
    276512    settingsList = ['plot.show_legend', 'plot.symbol_size', 'plot.show_x_axis_title', 'plot.show_y_axis_title', 
  • orange/OrangeWidgets/plot/owplot3d.py

    r8922 r8927  
    1515import os 
    1616import time 
    17 from math import sin, cos, pi, floor, ceil, log10 
     17from math import sin, cos, pi 
    1818import struct 
    1919 
     
    3131from owlegend import OWLegend, OWLegendItem, OWLegendTitle, OWLegendGradient 
    3232from owopenglrenderer import OWOpenGLRenderer 
    33 from owconstants import ZOOMING 
     33from owconstants import ZOOMING, PANNING 
    3434 
    3535from OWColorPalette import ColorPaletteGenerator 
     
    5555    pass 
    5656 
    57 def plane_visible(plane, location): 
    58     normal = normal_from_points(*plane[:3]) 
    59     loc_plane = normalize(plane[0] - location) 
    60     if numpy.dot(normal, loc_plane) > 0: 
    61         return False 
    62     return True 
    63  
    64 def nicenum(x, round): 
    65     if x <= 0.: 
    66         return x # TODO: what to do in such cases? 
    67     expv = floor(log10(x)) 
    68     f = x / pow(10., expv) 
    69     if round: 
    70         if f < 1.5: nf = 1. 
    71         elif f < 3.: nf = 2. 
    72         elif f < 7.: nf = 5. 
    73         else: nf = 10. 
    74     else: 
    75         if f <= 1.: nf = 1. 
    76         elif f <= 2.: nf = 2. 
    77         elif f <= 5.: nf = 5. 
    78         else: nf = 10. 
    79     return nf * pow(10., expv) 
    80  
    81 def loose_label(min_value, max_value, num_ticks): 
    82     '''Algorithm by Paul S. Heckbert (Graphics Gems). 
    83        Generates a list of "nice" values between min and max, 
    84        given the number of ticks. Also returns the number 
    85        of fractional digits to use. 
    86     ''' 
    87     range = nicenum(max_value-min_value, False) 
    88     d = nicenum(range / float(num_ticks-1), True) 
    89     if d <= 0.: # TODO 
    90         return numpy.arange(min_value, max_value, (max_value-min_value)/num_ticks), 1 
    91     plot_min = floor(min_value / d) * d 
    92     plot_max = ceil(max_value / d) * d 
    93     num_frac = int(max(-floor(log10(d)), 0)) 
    94     return numpy.arange(plot_min, plot_max + 0.5*d, d), num_frac 
    95  
    9657def enum(*sequential): 
    9758    enums = dict(zip(sequential, range(len(sequential)))) 
     
    10667              'DIAMOND', 'WEDGE', 'LWEDGE', 'CROSS', 'XCROSS') 
    10768 
    108 # TODO: move to scatterplot 
    109 Axis = enum('X', 'Y', 'Z', 'CUSTOM') 
    110  
    111 from plot.primitives import normal_from_points, get_symbol_geometry, clamp, normalize, GeometryType 
     69from plot.primitives import get_symbol_geometry, clamp, normalize, GeometryType 
    11270 
    11371class OWLegend3D(OWLegend): 
     
    239197 
    240198        self.setMouseTracking(True) 
    241         self.mouse_position = QPoint(0, 0) 
     199        self._mouse_position = QPoint(0, 0) 
    242200        self.invert_mouse_x = False 
    243201        self.mouse_sensitivity = 5 
    244  
    245         # TODO: these should be moved down to Scatterplot3D 
    246         self.x_axis_labels = None 
    247         self.y_axis_labels = None 
    248         self.z_axis_labels = None 
    249  
    250         self.x_axis_title = '' 
    251         self.y_axis_title = '' 
    252         self.z_axis_title = '' 
    253  
    254         self.show_x_axis_title = self.show_y_axis_title = self.show_z_axis_title = True 
    255202 
    256203        self.additional_scale = array([0., 0., 0.]) 
     
    263210 
    264211        self._theme = PlotTheme() 
    265         self.show_axes = True 
    266  
    267         self.tooltip_fbo_dirty = True 
    268         self.tooltip_win_center = [0, 0] 
     212 
     213        self._tooltip_fbo_dirty = True 
     214        self._tooltip_win_center = [0, 0] 
    269215 
    270216        self._use_fbos = True 
     
    277223        self.fade_outside = True 
    278224        self.label_index = -1 
    279  
    280         self.build_axes() 
    281225 
    282226        self.data = None 
     
    448392        format = QtOpenGL.QGLFramebufferObjectFormat() 
    449393        format.setAttachment(QtOpenGL.QGLFramebufferObject.Depth) 
    450         self.tooltip_fbo = QtOpenGL.QGLFramebufferObject(256, 256, format) 
    451         if self.tooltip_fbo.isValid(): 
     394        self._tooltip_fbo = QtOpenGL.QGLFramebufferObject(256, 256, format) 
     395        if self._tooltip_fbo.isValid(): 
    452396            print('Tooltip FBO created.') 
    453397        else: 
     
    504448            self.before_draw_callback() 
    505449 
    506         if self.show_axes: 
    507             self.draw_axes() 
    508  
    509450        plot_scale = numpy.maximum([1e-5, 1e-5, 1e-5], self.plot_scale+self.additional_scale) 
    510451 
     
    530471            glDrawArrays(GL_TRIANGLES, 0, self.num_primitives_generated*3) 
    531472            glBindVertexArray(0) 
    532         else: 
     473        elif not self._use_opengl_3: 
    533474            glDisable(GL_CULL_FACE) 
    534475            glEnable(GL_DEPTH_TEST) 
     
    544485            self.after_draw_callback() 
    545486 
    546         if self.tooltip_fbo_dirty: 
    547             self.tooltip_fbo.bind() 
     487        if self._tooltip_fbo_dirty: 
     488            self._tooltip_fbo.bind() 
    548489            glClearColor(1, 1, 1, 1) 
    549490            glClearDepth(1) 
     
    552493            glEnable(GL_DEPTH_TEST) 
    553494 
    554             glViewport(-self.mouse_position.x()+128, -(self.height()-self.mouse_position.y())+128, self.width(), self.height()) 
    555             self.tooltip_win_center = [self.mouse_position.x(), self.mouse_position.y()] 
     495            glViewport(-self._mouse_position.x()+128, -(self.height()-self._mouse_position.y())+128, self.width(), self.height()) 
     496            self._tooltip_win_center = [self._mouse_position.x(), self._mouse_position.y()] 
    556497 
    557498            self.symbol_program.bind() 
     
    562503                glDrawArrays(GL_TRIANGLES, 0, self.num_primitives_generated*3) 
    563504                glBindVertexArray(0) 
    564             else: 
     505            elif not self._use_opengl_3: 
    565506                orangeqt.Plot3D.draw_data_solid(self) 
    566507            self.symbol_program.release() 
    567             self.tooltip_fbo.release() 
    568             self.tooltip_fbo_dirty = False 
     508            self._tooltip_fbo.release() 
     509            self._tooltip_fbo_dirty = False 
    569510            glViewport(0, 0, self.width(), self.height()) 
    570511 
     
    619560 
    620561        if self._state == PlotState.SCALING: 
    621             x, y = self.mouse_position.x(), self.mouse_position.y() 
     562            x, y = self._mouse_position.x(), self._mouse_position.y() 
    622563            self.renderer.draw_triangle(QVector3D(x-5, y-30, 0), 
    623564                                        QVector3D(x+5, y-30, 0), 
     
    676617                                    QVector3D(self._selection.left(), self._selection.top(), 0), 
    677618                                    border_color, border_color) 
    678  
    679     def build_axes(self): 
    680         edge_half = 1. / 2. 
    681         x_axis = [[-edge_half, -edge_half, -edge_half], [edge_half, -edge_half, -edge_half]] 
    682         y_axis = [[-edge_half, -edge_half, -edge_half], [-edge_half, edge_half, -edge_half]] 
    683         z_axis = [[-edge_half, -edge_half, -edge_half], [-edge_half, -edge_half, edge_half]] 
    684  
    685         self.x_axis = x_axis = numpy.array(x_axis) 
    686         self.y_axis = y_axis = numpy.array(y_axis) 
    687         self.z_axis = z_axis = numpy.array(z_axis) 
    688  
    689         self.unit_x = unit_x = numpy.array([1., 0., 0.]) 
    690         self.unit_y = unit_y = numpy.array([0., 1., 0.]) 
    691         self.unit_z = unit_z = numpy.array([0., 0., 1.]) 
    692   
    693         A = y_axis[1] 
    694         B = y_axis[1] + unit_x 
    695         C = x_axis[1] 
    696         D = x_axis[0] 
    697  
    698         E = A + unit_z 
    699         F = B + unit_z 
    700         G = C + unit_z 
    701         H = D + unit_z 
    702  
    703         self.axis_plane_xy = [A, B, C, D] 
    704         self.axis_plane_yz = [A, D, H, E] 
    705         self.axis_plane_xz = [D, C, G, H] 
    706  
    707         self.axis_plane_xy_back = [H, G, F, E] 
    708         self.axis_plane_yz_right = [B, F, G, C] 
    709         self.axis_plane_xz_top = [E, F, B, A] 
    710  
    711     def draw_axes(self): 
    712         glMatrixMode(GL_PROJECTION) 
    713         glLoadIdentity() 
    714         glMultMatrixd(numpy.array(self.projection.data(), dtype=float)) 
    715         glMatrixMode(GL_MODELVIEW) 
    716         glLoadIdentity() 
    717         glMultMatrixd(numpy.array(self.modelview.data(), dtype=float)) 
    718  
    719         self.renderer.set_transform(self.projection, self.modelview) 
    720  
    721         def draw_axis(line): 
    722             self.qglColor(self._theme.axis_color) 
    723             glLineWidth(2) # TODO: how to draw thick lines? 
    724             glBegin(GL_LINES) 
    725             glVertex3f(*line[0]) 
    726             glVertex3f(*line[1]) 
    727             glEnd() 
    728  
    729         def draw_discrete_axis_values(axis, coord_index, normal, axis_labels): 
    730             start, end = axis.copy() 
    731             start_value = self.map_to_data(start.copy())[coord_index] 
    732             end_value = self.map_to_data(end.copy())[coord_index] 
    733             length = end_value - start_value 
    734             for i, label in enumerate(axis_labels): 
    735                 value = (i + 1) * 2 
    736                 if start_value <= value <= end_value: 
    737                     position = start + (end-start)*((value-start_value) / length) 
    738                     self.renderer.draw_line( 
    739                         QVector3D(*position), 
    740                         QVector3D(*(position + normal*0.03)), 
    741                         color=self._theme.axis_values_color) 
    742                     position += normal * 0.1 
    743                     self.renderText(position[0], 
    744                                     position[1], 
    745                                     position[2], 
    746                                     label, font=self._theme.labels_font) 
    747  
    748         def draw_values(axis, coord_index, normal, axis_labels): 
    749             glLineWidth(1) 
    750             if axis_labels != None: 
    751                 draw_discrete_axis_values(axis, coord_index, normal, axis_labels) 
    752                 return 
    753             start, end = axis.copy() 
    754             start_value = self.map_to_data(start.copy())[coord_index] 
    755             end_value = self.map_to_data(end.copy())[coord_index] 
    756             values, num_frac = loose_label(start_value, end_value, 7) 
    757             for value in values: 
    758                 if not (start_value <= value <= end_value): 
    759                     continue 
    760                 position = start + (end-start)*((value-start_value) / float(end_value-start_value)) 
    761                 text = ('%%.%df' % num_frac) % value 
    762                 self.renderer.draw_line( 
    763                     QVector3D(*position), 
    764                     QVector3D(*(position+normal*0.03)), 
    765                     color=self._theme.axis_values_color) 
    766                 position += normal * 0.1 
    767                 self.renderText(position[0], 
    768                                 position[1], 
    769                                 position[2], 
    770                                 text, font=self._theme.axis_font) 
    771  
    772         def draw_axis_title(axis, title, normal): 
    773             middle = (axis[0] + axis[1]) / 2. 
    774             middle += normal * 0.1 if axis[0][1] != axis[1][1] else normal * 0.2 
    775             self.renderText(middle[0], middle[1], middle[2], 
    776                             title, 
    777                             font=self._theme.axis_title_font) 
    778  
    779         glDisable(GL_DEPTH_TEST) 
    780         glLineWidth(1) 
    781         glEnable(GL_BLEND) 
    782         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
    783  
    784         cam_in_space = numpy.array([ 
    785           self.camera[0]*self.camera_distance, 
    786           self.camera[1]*self.camera_distance, 
    787           self.camera[2]*self.camera_distance 
    788         ]) 
    789  
    790         planes = [self.axis_plane_xy, self.axis_plane_yz, 
    791                   self.axis_plane_xy_back, self.axis_plane_yz_right] 
    792         normals = [[numpy.array([0,-1, 0]), numpy.array([-1, 0, 0])], 
    793                    [numpy.array([0, 0,-1]), numpy.array([ 0,-1, 0])], 
    794                    [numpy.array([0,-1, 0]), numpy.array([-1, 0, 0])], 
    795                    [numpy.array([0,-1, 0]), numpy.array([ 0, 0,-1])]] 
    796         visible_planes = [plane_visible(plane, cam_in_space) for plane in planes] 
    797         xz_visible = not plane_visible(self.axis_plane_xz, cam_in_space) 
    798  
    799         if visible_planes[0 if xz_visible else 2]: 
    800             draw_axis(self.x_axis) 
    801             draw_values(self.x_axis, 0, numpy.array([0, 0, -1]), self.x_axis_labels) 
    802             if self.show_x_axis_title: 
    803                 draw_axis_title(self.x_axis, self.x_axis_title, numpy.array([0, 0, -1])) 
    804         elif visible_planes[2 if xz_visible else 0]: 
    805             draw_axis(self.x_axis + self.unit_z) 
    806             draw_values(self.x_axis + self.unit_z, 0, numpy.array([0, 0, 1]), self.x_axis_labels) 
    807             if self.show_x_axis_title: 
    808                 draw_axis_title(self.x_axis + self.unit_z, 
    809                                 self.x_axis_title, numpy.array([0, 0, 1])) 
    810  
    811         if visible_planes[1 if xz_visible else 3]: 
    812             draw_axis(self.z_axis) 
    813             draw_values(self.z_axis, 2, numpy.array([-1, 0, 0]), self.z_axis_labels) 
    814             if self.show_z_axis_title: 
    815                 draw_axis_title(self.z_axis, self.z_axis_title, numpy.array([-1, 0, 0])) 
    816         elif visible_planes[3 if xz_visible else 1]: 
    817             draw_axis(self.z_axis + self.unit_x) 
    818             draw_values(self.z_axis + self.unit_x, 2, numpy.array([1, 0, 0]), self.z_axis_labels) 
    819             if self.show_z_axis_title: 
    820                 draw_axis_title(self.z_axis + self.unit_x, self.z_axis_title, numpy.array([1, 0, 0])) 
    821  
    822         try: 
    823             rightmost_visible = visible_planes[::-1].index(True) 
    824         except ValueError: 
    825             return 
    826         if rightmost_visible == 0 and visible_planes[0] == True: 
    827             rightmost_visible = 3 
    828         y_axis_translated = [self.y_axis+self.unit_x, 
    829                              self.y_axis+self.unit_x+self.unit_z, 
    830                              self.y_axis+self.unit_z, 
    831                              self.y_axis] 
    832         normals = [numpy.array([1, 0, 0]), 
    833                    numpy.array([0, 0, 1]), 
    834                    numpy.array([-1,0, 0]), 
    835                    numpy.array([0, 0,-1])] 
    836         axis = y_axis_translated[rightmost_visible] 
    837         normal = normals[rightmost_visible] 
    838         draw_axis(axis) 
    839         draw_values(axis, 1, normal, self.y_axis_labels) 
    840         if self.show_y_axis_title: 
    841             draw_axis_title(axis, self.y_axis_title, normal) 
    842619 
    843620    def set_shown_attributes(self, 
     
    959736        orangeqt.Plot3D.set_valid_data(self, long(self.valid_data.ctypes.data)) 
    960737 
    961     # TODO: to scatterplot 
    962     def set_axis_labels(self, axis_id, labels): 
    963         '''labels should be a list of strings''' 
    964         if Axis.is_valid(axis_id) and axis_id != Axis.CUSTOM: 
    965             setattr(self, Axis.to_str(axis_id).lower() + '_axis_labels', labels) 
    966  
    967     def set_axis_title(self, axis_id, title): 
    968         if Axis.is_valid(axis_id) and axis_id != Axis.CUSTOM: 
    969             setattr(self, Axis.to_str(axis_id).lower() + '_axis_title', title) 
    970  
    971     def set_show_axis_title(self, axis_id, show): 
    972         if Axis.is_valid(axis_id) and axis_id != Axis.CUSTOM: 
    973             setattr(self, 'show_' + Axis.to_str(axis_id).lower() + '_axis_title', show) 
    974  
    975738    def set_new_zoom(self, x_min, x_max, y_min, y_max, z_min, z_max, plot_coordinates=False): 
    976739        '''Specifies new zoom in data or plot coordinates.''' 
     
    1071834 
    1072835    def mousePressEvent(self, event): 
    1073         pos = self.mouse_position = event.pos() 
     836        pos = self._mouse_position = event.pos() 
    1074837        buttons = event.buttons() 
    1075838 
     
    1084847                self.setCursor(Qt.ClosedHandCursor) 
    1085848                self._state = PlotState.DRAGGING_LEGEND 
     849            elif self.state == PANNING: 
     850                self._state = PlotState.PANNING 
    1086851            else: 
    1087852                self._state = PlotState.SELECTING 
     
    1090855            if QApplication.keyboardModifiers() & Qt.ShiftModifier: 
    1091856                self._state = PlotState.SCALING 
    1092                 self.scaling_init_pos = self.mouse_position 
     857                self.scaling_init_pos = self._mouse_position 
    1093858                self.additional_scale = array([0., 0., 0.]) 
    1094859            else: 
     
    1103868    def _check_mouseover(self, pos): 
    1104869        if self.mouseover_callback != None and self._state == PlotState.IDLE: 
    1105             if abs(pos.x() - self.tooltip_win_center[0]) > 100 or\ 
    1106                abs(pos.y() - self.tooltip_win_center[1]) > 100: 
    1107                 self.tooltip_fbo_dirty = True 
     870            if abs(pos.x() - self._tooltip_win_center[0]) > 100 or\ 
     871               abs(pos.y() - self._tooltip_win_center[1]) > 100: 
     872                self._tooltip_fbo_dirty = True 
    1108873                self.update() 
    1109874            # Use pixel-color-picking to read example index under mouse cursor (also called ID rendering). 
    1110             self.tooltip_fbo.bind() 
    1111             value = glReadPixels(pos.x() - self.tooltip_win_center[0] + 128, 
    1112                                  self.tooltip_win_center[1] - pos.y() + 128, 
     875            self._tooltip_fbo.bind() 
     876            value = glReadPixels(pos.x() - self._tooltip_win_center[0] + 128, 
     877                                 self._tooltip_win_center[1] - pos.y() + 128, 
    1113878                                 1, 1, 
    1114879                                 GL_RGBA, 
    1115880                                 GL_UNSIGNED_BYTE) 
    1116             self.tooltip_fbo.release() 
     881            self._tooltip_fbo.release() 
    1117882            value = struct.unpack('I', value)[0] 
    1118883            # Check if value is less than 4294967295 ( 
     
    1127892        self._check_mouseover(pos) 
    1128893 
    1129         dx = pos.x() - self.mouse_position.x() 
    1130         dy = pos.y() - self.mouse_position.y() 
     894        dx = pos.x() - self._mouse_position.x() 
     895        dy = pos.y() - self._mouse_position.y() 
    1131896 
    1132897        if self.invert_mouse_x: 
     
    1171936                self.unsetCursor() 
    1172937 
    1173         self.mouse_position = pos 
     938        self._mouse_position = pos 
    1174939        self.update() 
    1175940 
     
    1203968                    self.auto_send_selection_callback() 
    1204969 
    1205         self.tooltip_fbo_dirty = True 
     970        self._tooltip_fbo_dirty = True 
    1206971        self.unsetCursor() 
    1207972        self._state = PlotState.IDLE 
     
    1212977            delta = 1 + event.delta() / self.zoom_factor 
    1213978            self.plot_scale *= delta 
    1214             self.tooltip_fbo_dirty = True 
     979            self._tooltip_fbo_dirty = True 
    1215980            self.update() 
    1216981 
     
    12391004 
    12401005    def show_tooltip(self, text): 
    1241         x, y = self.mouse_position.x(), self.mouse_position.y() 
     1006        x, y = self._mouse_position.x(), self._mouse_position.y() 
    12421007        QToolTip.showText(self.mapToGlobal(QPoint(x, y)), text, self, QRect(x-3, y-3, 6, 6)) 
    12431008 
     
    12461011        self.data_scale = array([1., 1., 1.]) 
    12471012        self.data_translation = array([0., 0., 0.]) 
    1248         self.x_axis_labels = None 
    1249         self.y_axis_labels = None 
    1250         self.z_axis_labels = None 
    1251         self.tooltip_fbo_dirty = True 
     1013        self._tooltip_fbo_dirty = True 
    12521014        self.feedback_generated = False 
    12531015 
Note: See TracChangeset for help on using the changeset viewer.