예제 #1
0
 def tunit_cube(self, vals=None, M=None):
     if M is None:
         M = self.M
     xyzs = self.unit_cube(vals)
     tcube = proj3d.proj_points(xyzs, M)
     return tcube
예제 #2
0
    def draw(self, renderer):
        #
        self.label._transform = self.axes.transData
        renderer.open_group("axis3d")
        ticklabelBoxes = []
        ticklabelBoxes2 = []

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)]
        #
        minx, maxx, miny, maxy, minz, maxz = self.axes.get_w_lims()

        interval = self.get_view_interval()
        # filter locations here so that no extra grid lines are drawn
        majorLocs = [loc for loc in majorLocs if interval.contains(loc)]
        # these will generate spacing for labels and ticks
        dx = (maxx - minx) / 12
        dy = (maxy - miny) / 12
        dz = (maxz - minz) / 12

        # stretch the boundary slightly so that the ticks have a better fit
        minx, maxx, miny, maxy, minz, maxz = (
            minx - dx / 4,
            maxx + dx / 4,
            miny - dy / 4,
            maxy + dy / 4,
            minz - dz / 4,
            maxz + dz / 4,
        )

        # generate the unit_cubes and transformed unit_cubes from the stretched
        # limits
        vals = minx, maxx, miny, maxy, minz, maxz
        uc = self.axes.unit_cube(vals)
        tc = self.axes.tunit_cube(vals, renderer.M)
        #
        # these are flags which decide whether the axis should be drawn
        # on the high side (ie on the high side of the paired axis)
        xhigh = tc[1][2] > tc[2][2]
        yhigh = tc[3][2] > tc[2][2]
        zhigh = tc[0][2] > tc[2][2]
        #
        aoff = 0

        # lx,ly,lz are the label positions in user coordinates
        # to and te are the locations of the origin and the end of the axis
        #
        if self.adir == "x":
            lx = (minx + maxx) / 2
            if xhigh:
                # xaxis at front
                self.set_pane_fg([tc[0], tc[1], tc[5], tc[4]])
                to = tc[3]
                te = tc[2]
                xyz = [(x, maxy, minz) for x in majorLocs]
                nxyz = [(x, miny, minz) for x in majorLocs]
                lxyz = [(x, miny, maxz) for x in majorLocs]
                aoff = -90

                ly = maxy + dy
                lz = minz - dz
            else:
                self.set_pane_bg([tc[3], tc[2], tc[6], tc[7]])
                to = tc[0]
                te = tc[1]
                xyz = [(x, miny, minz) for x in majorLocs]
                nxyz = [(x, maxy, minz) for x in majorLocs]
                lxyz = [(x, maxy, maxz) for x in majorLocs]
                aoff = 90

                ly = miny - dy
                lz = minz - dz

        elif self.adir == "y":
            # cube 3 is minx,maxy,minz
            # cube 2 is maxx,maxy,minz
            ly = (maxy + miny) / 2
            if yhigh:
                # yaxis at front
                self.set_pane_fg([tc[0], tc[3], tc[7], tc[4]])
                to = tc[1]
                te = tc[2]
                xyz = [(maxx, y, minz) for y in majorLocs]
                nxyz = [(minx, y, minz) for y in majorLocs]
                lxyz = [(minx, y, maxz) for y in majorLocs]
                aoff = 90

                #
                lx = maxx + dx
                lz = minz - dz

            else:
                # yaxis at back
                self.set_pane_bg([tc[1], tc[5], tc[6], tc[2]])
                to = tc[0]
                te = tc[3]
                xyz = [(minx, y, minz) for y in majorLocs]
                nxyz = [(maxx, y, minz) for y in majorLocs]
                lxyz = [(maxx, y, maxz) for y in majorLocs]
                aoff = -90
                #
                lx = minx - dx
                lz = minz - dz

        elif self.adir == "z":
            nxyz = None
            self.set_pane_bg([tc[0], tc[1], tc[2], tc[3]])
            aoff = -90
            lz = (maxz + minz) / 2
            if xhigh and yhigh:
                to = tc[1]
                te = tc[5]
                xyz = [(maxx, miny, z) for z in majorLocs]
                nxyz = [(minx, miny, z) for z in majorLocs]
                lxyz = [(minx, maxy, z) for z in majorLocs]
                #
                lx = maxx + dx
                ly = miny - dy
            elif xhigh and not yhigh:
                to = tc[2]
                te = tc[6]
                xyz = [(maxx, maxy, z) for z in majorLocs]
                nxyz = [(maxx, miny, z) for z in majorLocs]
                lxyz = [(minx, miny, z) for z in majorLocs]

                lx = maxx + dx
                ly = maxy + dy
            elif yhigh and not xhigh:
                to = tc[0]
                te = tc[4]
                xyz = [(minx, miny, z) for z in majorLocs]
                nxyz = [(minx, maxy, z) for z in majorLocs]
                lxyz = [(maxx, maxy, z) for z in majorLocs]
                lx = minx - dx
                ly = miny - dy
            else:
                to = tc[3]
                te = tc[7]
                xyz = [(minx, maxy, z) for z in majorLocs]
                nxyz = [(maxx, maxy, z) for z in majorLocs]
                lxyz = [(maxx, miny, z) for z in majorLocs]
                lx = minx - dx
                ly = maxy + dy

        #
        tlx, tly, tlz = proj3d.proj_transform(lx, ly, lz, renderer.M)
        self.label.set_position((tlx, tly))

        self.label.set_va("center")
        # print self.label._text, lx,ly, tlx,tly
        #
        self.pane.draw(renderer)
        # TODO - why didn't this work earlier ?
        self.pane.set_transform(self.axes.transData)
        self.gridlines.set_transform(self.axes.transData)
        #
        self.line.set_transform(self.axes.transData)
        self.line.set_data((to[0], te[0]), (to[1], te[1]))
        self.line.draw(renderer)

        angle = norm_angle(math.degrees(math.atan2(te[1] - to[1], te[0] - to[0])))
        #
        # should be some other enabler here...
        if len(self.label._text) > 1:
            if abs(angle) > 90 and self.adir != "z":
                la = angle + 180
            else:
                la = angle
            # almight kludge - the text angles seem to be incorrect
            # (at-least for gtkagg backend...)
            # this seems to more or less fix the problem...
            if 0:
                rla = math.radians(la)
                # -15 gives the closest result ... but the perspective projection is
                # then slightly broken..
                erra = -12 * math.cos(rla) * math.sin(rla)
                self.label.set_rotation(la + erra)
            else:
                self.label.set_rotation(la)

        #
        self.label.draw(renderer)
        #
        angle = angle + aoff

        if xyz:
            points = proj3d.proj_points(xyz, renderer.M)
        if nxyz:
            tnxyz = proj3d.proj_points(nxyz, renderer.M)
            tlxyz = proj3d.proj_points(lxyz, renderer.M)
            lines = zip(xyz, nxyz, lxyz)
            self.gridlines.segments_3d = lines
            self.gridlines._colors = [(0.9, 0.9, 0.9, 1)] * len(lines)
            # self.gridlines._colors = [(0.98,0.98,0.98,1.0)]*len(lines)
            self.gridlines.draw(renderer)

        if xyz:
            seen = {}
            interval = self.get_view_interval()
            for tick, loc, (x, y, z), label in zip(majorTicks, majorLocs, points, majorLabels):
                if tick is None:
                    continue
                if not interval.contains(loc):
                    continue
                seen[loc] = 1
                tick_update_position(tick, x, y, z, angle=angle)
                tick.set_label1(label)
                tick.set_label2(label)
                tick.draw(renderer)
                if tick.label1On:
                    extent = tick.label1.get_window_extent(renderer)
                    ticklabelBoxes.append(extent)
                if tick.label2On:
                    extent = tick.label2.get_window_extent(renderer)
                    ticklabelBoxes2.append(extent)
        #
        renderer.close_group("axis3d")
예제 #3
0
    def draw(self, renderer):
        #
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d')
        ticklabelBoxes = []
        ticklabelBoxes2 = []

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [
            self.major.formatter(val, i) for i, val in enumerate(majorLocs)
        ]
        #
        minx, maxx, miny, maxy, minz, maxz = self.axes.get_w_lims()

        interval = self.get_view_interval()
        # filter locations here so that no extra grid lines are drawn
        majorLocs = [loc for loc in majorLocs if interval.contains(loc)]
        # these will generate spacing for labels and ticks
        dx = (maxx - minx) / 12
        dy = (maxy - miny) / 12
        dz = (maxz - minz) / 12

        # stretch the boundary slightly so that the ticks have a better fit
        minx, maxx, miny, maxy, minz, maxz = (minx - dx / 4, maxx + dx / 4,
                                              miny - dy / 4, maxy + dy / 4,
                                              minz - dz / 4, maxz + dz / 4)

        # generate the unit_cubes and transformed unit_cubes from the stretched
        # limits
        vals = minx, maxx, miny, maxy, minz, maxz
        uc = self.axes.unit_cube(vals)
        tc = self.axes.tunit_cube(vals, renderer.M)
        #
        # these are flags which decide whether the axis should be drawn
        # on the high side (ie on the high side of the paired axis)
        xhigh = tc[1][2] > tc[2][2]
        yhigh = tc[3][2] > tc[2][2]
        zhigh = tc[0][2] > tc[2][2]
        #
        aoff = 0

        # lx,ly,lz are the label positions in user coordinates
        # to and te are the locations of the origin and the end of the axis
        #
        if self.adir == 'x':
            lx = (minx + maxx) / 2
            if xhigh:
                # xaxis at front
                self.set_pane_fg([tc[0], tc[1], tc[5], tc[4]])
                to = tc[3]
                te = tc[2]
                xyz = [(x, maxy, minz) for x in majorLocs]
                nxyz = [(x, miny, minz) for x in majorLocs]
                lxyz = [(x, miny, maxz) for x in majorLocs]
                aoff = -90

                ly = maxy + dy
                lz = minz - dz
            else:
                self.set_pane_bg([tc[3], tc[2], tc[6], tc[7]])
                to = tc[0]
                te = tc[1]
                xyz = [(x, miny, minz) for x in majorLocs]
                nxyz = [(x, maxy, minz) for x in majorLocs]
                lxyz = [(x, maxy, maxz) for x in majorLocs]
                aoff = 90

                ly = miny - dy
                lz = minz - dz

        elif self.adir == 'y':
            # cube 3 is minx,maxy,minz
            # cube 2 is maxx,maxy,minz
            ly = (maxy + miny) / 2
            if yhigh:
                # yaxis at front
                self.set_pane_fg([tc[0], tc[3], tc[7], tc[4]])
                to = tc[1]
                te = tc[2]
                xyz = [(maxx, y, minz) for y in majorLocs]
                nxyz = [(minx, y, minz) for y in majorLocs]
                lxyz = [(minx, y, maxz) for y in majorLocs]
                aoff = 90

                #
                lx = maxx + dx
                lz = minz - dz

            else:
                # yaxis at back
                self.set_pane_bg([tc[1], tc[5], tc[6], tc[2]])
                to = tc[0]
                te = tc[3]
                xyz = [(minx, y, minz) for y in majorLocs]
                nxyz = [(maxx, y, minz) for y in majorLocs]
                lxyz = [(maxx, y, maxz) for y in majorLocs]
                aoff = -90
                #
                lx = minx - dx
                lz = minz - dz

        elif self.adir == 'z':
            nxyz = None
            self.set_pane_bg([tc[0], tc[1], tc[2], tc[3]])
            aoff = -90
            lz = (maxz + minz) / 2
            if xhigh and yhigh:
                to = tc[1]
                te = tc[5]
                xyz = [(maxx, miny, z) for z in majorLocs]
                nxyz = [(minx, miny, z) for z in majorLocs]
                lxyz = [(minx, maxy, z) for z in majorLocs]
                #
                lx = maxx + dx
                ly = miny - dy
            elif xhigh and not yhigh:
                to = tc[2]
                te = tc[6]
                xyz = [(maxx, maxy, z) for z in majorLocs]
                nxyz = [(maxx, miny, z) for z in majorLocs]
                lxyz = [(minx, miny, z) for z in majorLocs]

                lx = maxx + dx
                ly = maxy + dy
            elif yhigh and not xhigh:
                to = tc[0]
                te = tc[4]
                xyz = [(minx, miny, z) for z in majorLocs]
                nxyz = [(minx, maxy, z) for z in majorLocs]
                lxyz = [(maxx, maxy, z) for z in majorLocs]
                lx = minx - dx
                ly = miny - dy
            else:
                to = tc[3]
                te = tc[7]
                xyz = [(minx, maxy, z) for z in majorLocs]
                nxyz = [(maxx, maxy, z) for z in majorLocs]
                lxyz = [(maxx, miny, z) for z in majorLocs]
                lx = minx - dx
                ly = maxy + dy

        #
        tlx, tly, tlz = proj3d.proj_transform(lx, ly, lz, renderer.M)
        self.label.set_position((tlx, tly))

        self.label.set_va('center')
        #print self.label._text, lx,ly, tlx,tly
        #
        self.pane.draw(renderer)
        #TODO - why didn't this work earlier ?
        self.pane.set_transform(self.axes.transData)
        self.gridlines.set_transform(self.axes.transData)
        #
        self.line.set_transform(self.axes.transData)
        self.line.set_data((to[0], te[0]), (to[1], te[1]))
        self.line.draw(renderer)

        angle = norm_angle(
            math.degrees(math.atan2(te[1] - to[1], te[0] - to[0])))
        #
        # should be some other enabler here...
        if len(self.label._text) > 1:
            if abs(angle) > 90 and self.adir != 'z':
                la = angle + 180
            else:
                la = angle
            # almight kludge - the text angles seem to be incorrect
            # (at-least for gtkagg backend...)
            # this seems to more or less fix the problem...
            if 0:
                rla = math.radians(la)
                # -15 gives the closest result ... but the perspective projection is
                # then slightly broken..
                erra = -12 * math.cos(rla) * math.sin(rla)
                self.label.set_rotation(la + erra)
            else:
                self.label.set_rotation(la)

        #
        self.label.draw(renderer)
        #
        angle = angle + aoff

        if xyz:
            points = proj3d.proj_points(xyz, renderer.M)
        if nxyz:
            tnxyz = proj3d.proj_points(nxyz, renderer.M)
            tlxyz = proj3d.proj_points(lxyz, renderer.M)
            lines = zip(xyz, nxyz, lxyz)
            self.gridlines.segments_3d = lines
            self.gridlines._colors = [(0.9, 0.9, 0.9, 1)] * len(lines)
            #self.gridlines._colors = [(0.98,0.98,0.98,1.0)]*len(lines)
            self.gridlines.draw(renderer)

        if xyz:
            seen = {}
            interval = self.get_view_interval()
            for tick, loc, (x, y, z), label in zip(majorTicks, majorLocs,
                                                   points, majorLabels):
                if tick is None: continue
                if not interval.contains(loc): continue
                seen[loc] = 1
                tick_update_position(tick, x, y, z, angle=angle)
                tick.set_label1(label)
                tick.set_label2(label)
                tick.draw(renderer)
                if tick.label1On:
                    extent = tick.label1.get_window_extent(renderer)
                    ticklabelBoxes.append(extent)
                if tick.label2On:
                    extent = tick.label2.get_window_extent(renderer)
                    ticklabelBoxes2.append(extent)
        #
        renderer.close_group('axis3d')