예제 #1
0
 def draw3d(self, renderer):
     xyslist = [
         proj3d.proj_trans_points(points, renderer.M) for points in
         self.segments_3d]
     segments_2d = [zip(xs,ys) for (xs,ys,zs) in xyslist]
     self._segments = segments_2d
     self.draw2d(renderer)
예제 #2
0
 def draw(self, renderer):
     orig_segments = self._segments
     xyslist = [proj3d.proj_trans_points(points, renderer.M) for points in self.segments_3d]
     segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
     self._segments = segments_2d
     LineCollection.draw(self, renderer)
     self._segments = orig_segments
예제 #3
0
 def draw3d(self, renderer):
     #
     segments_3d = [[juggle_axes(x, y, self.z, self.dir) for (x, y) in points] for points in self._segments]
     xyslist = [proj3d.proj_trans_points(points, renderer.M) for points in segments_3d]
     segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
     # orig_segments = self._segments
     self._segments = segments_2d
     self.draw2d(renderer)
예제 #4
0
def draw_linec(self, renderer):
    orig_segments = self._segments
    segments_3d = [[(x, y, z) for (x, y), z in zip(points, zs)] for zs, points in zip(self.zs, self._segments)]
    xyslist = [proj3d.proj_trans_points(points, renderer.M) for points in segments_3d]
    segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
    self._segments = segments_2d
    LineCollection.draw(self, renderer)
    self._segments = orig_segments
예제 #5
0
파일: art3d.py 프로젝트: jtomase/matplotlib
 def draw3d(self, renderer):
     xyslist = [
         proj3d.proj_trans_points(points, renderer.M)
         for points in self.segments_3d
     ]
     segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
     self._segments = segments_2d
     self.draw2d(renderer)
예제 #6
0
파일: art3d.py 프로젝트: jtomase/matplotlib
 def draw(self, renderer):
     orig_segments = self._segments
     xyslist = [
         proj3d.proj_trans_points(points, renderer.M)
         for points in self.segments_3d
     ]
     segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
     self._segments = segments_2d
     LineCollection.draw(self, renderer)
     self._segments = orig_segments
예제 #7
0
파일: art3d.py 프로젝트: jtomase/matplotlib
def draw_linec(self, renderer):
    orig_segments = self._segments
    segments_3d = [[(x, y, z) for (x, y), z in zip(points, zs)]
                   for zs, points in zip(self.zs, self._segments)]
    xyslist = [
        proj3d.proj_trans_points(points, renderer.M) for points in segments_3d
    ]
    segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
    self._segments = segments_2d
    LineCollection.draw(self, renderer)
    self._segments = orig_segments
예제 #8
0
def draw_polyc(self, renderer):
    orig_segments = self._verts
    # process the list of lists of 2D points held in _verts to generate
    # a list of lists of 3D points
    segments_3d = [[(x, y, z) for (x, y), z in zip(points, self.zs)] for points in self._verts]
    #
    xyslist = [proj3d.proj_trans_points(points, renderer.M) for points in segments_3d]
    segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
    self._verts = segments_2d
    PolyCollection.draw(self, renderer)
    self._verts = orig_segments
예제 #9
0
 def draw(self, renderer):
     proj = proj3d.proj_trans_points([self._position3d, \
             self._position3d + self._dir_vec], renderer.M)
     dx = proj[0][1] - proj[0][0]
     dy = proj[1][1] - proj[1][0]
     if dx==0. and dy==0.:
         angle = 0.
     else:
         angle = math.degrees(math.atan2(dy, dx))
     self.set_position((proj[0][0], proj[1][0]))
     self.set_rotation(norm_text_angle(angle))
     mtext.Text.draw(self, renderer)
예제 #10
0
파일: art3d.py 프로젝트: jtomase/matplotlib
 def draw3d(self, renderer):
     #
     segments_3d = [[
         juggle_axes(x, y, self.z, self.dir) for (x, y) in points
     ] for points in self._segments]
     xyslist = [
         proj3d.proj_trans_points(points, renderer.M)
         for points in segments_3d
     ]
     segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
     #orig_segments = self._segments
     self._segments = segments_2d
     self.draw2d(renderer)
예제 #11
0
 def draw(self, renderer):
     proj = proj3d.proj_trans_points([self._position3d, \
             self._position3d + self._dir_vec], renderer.M)
     dx = proj[0][1] - proj[0][0]
     dy = proj[1][1] - proj[1][0]
     if dx == 0. and dy == 0.:
         # atan2 raises ValueError: math domain error on 0,0
         angle = 0.
     else:
         angle = math.degrees(math.atan2(dy, dx))
     self.set_position((proj[0][0], proj[1][0]))
     self.set_rotation(norm_text_angle(angle))
     mtext.Text.draw(self, renderer)
예제 #12
0
 def do_3d_projection(self, renderer):
     '''
     Project the points according to renderer matrix.
     '''
     xyslist = [
         proj3d.proj_trans_points(points, renderer.M) for points in
         self._segments3d]
     segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
     LineCollection.set_segments(self, segments_2d)
     minz = 1e9
     for (xs, ys, zs) in xyslist:
         minz = min(minz, min(zs))
     return minz
예제 #13
0
파일: art3d.py 프로젝트: jtomase/matplotlib
    def do_3d_projection(self, renderer):
        '''
        Project the points according to renderer matrix.
        '''
        xyslist = [
            proj3d.proj_trans_points(points, renderer.M) for points in
            self._segments3d]
        segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
        LineCollection.set_segments(self, segments_2d)

        minz = 1e9
        for (xs, ys, zs) in xyslist:
            minz = min(minz, min(zs))
        return minz
예제 #14
0
파일: art3d.py 프로젝트: jtomase/matplotlib
def draw_polyc(self, renderer):
    orig_segments = self._verts
    # process the list of lists of 2D points held in _verts to generate
    # a list of lists of 3D points
    segments_3d = [[(x, y, z) for (x, y), z in zip(points, self.zs)]
                   for points in self._verts]
    #
    xyslist = [
        proj3d.proj_trans_points(points, renderer.M) for points in segments_3d
    ]
    segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist]
    self._verts = segments_2d
    PolyCollection.draw(self, renderer)
    self._verts = orig_segments
예제 #15
0
    def draw_outline(self, renderer, face_sign=1):
        
        info = self._axinfo
        index = info['i']
       
        #if index != 1 : return
        
        #renderer.open_group('axis3d')
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d_Outline')

        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()


        # filter locations here so that no extra grid lines are drawn
        interval = self.get_view_interval()
        majorLocs = [loc for loc in majorLocs if \
                interval[0] <= loc <= interval[1]]
        self.major.formatter.set_locs(majorLocs)

        mins, maxs, centers, tickdelta, tc, highs = self._get_coord_info(renderer)
      

        # Draw ticks
        tickdir = info['tickdir']
        ticksign = np.where(highs == True, 1, -1)
        
        #isFront = [ highs[tickdir] * face_sign != 1], highs[tickdir] * face_sign != 1, highs[tickdir] * face_sign != 1 ]
        print ticksign

        if index == 0:
            ts = np.array( [( -ticksign[2],ticksign[2]), (-ticksign[1], ticksign[2]) , (-ticksign[1], -ticksign[2])])
            isVisible = ticksign[tickdir] * np.array([ -1, 1, 1])
        elif index == 1:
            ts = np.array( [( ticksign[0],ticksign[1]), (-ticksign[0], ticksign[2]) , (-ticksign[0], -ticksign[2])])
            isVisible = ticksign[tickdir] * np.array([ -ticksign[0], -1, ticksign[0]])
        elif index == 2:
            ts = np.array( [( ticksign[0],-ticksign[2]), (-ticksign[0], -ticksign[2]) , (-ticksign[0], -ticksign[1])])
            isVisible = ticksign[tickdir] * np.array([ -ticksign[0], 1, ticksign[0]])
        
        # Determine grid lines
        minmax = np.where(highs, maxs, mins)
        # Draw main axis line
        juggled = info['juggled']
        # Plot auxilary axis


        edgep_21 = minmax.copy()
        edgep_21[juggled[0]] = get_flip_min_max(edgep_21, juggled[0], mins, maxs)
        edgep_21[juggled[2]] = get_flip_min_max(edgep_21, juggled[2], mins, maxs)
        
        edgep_22 = edgep_21.copy()
        edgep_22[juggled[1]] = get_flip_min_max(edgep_22, juggled[1], mins, maxs)
        
        pep_aux    = proj3d.proj_trans_points([edgep_21, edgep_22], renderer.M)
        self.line_outline[0].set_data((pep_aux[0][0], pep_aux[0][1]), (pep_aux[1][0], pep_aux[1][1]))
           

        # 3rd axis
        edgep_31 = minmax.copy()
        edgep_31[juggled[2]] = get_flip_min_max(edgep_31, juggled[2], mins, maxs)
        edgep_32 = edgep_31.copy()
        edgep_32[juggled[1]] = get_flip_min_max(edgep_32, juggled[1], mins, maxs)
        
        pep_aux    = proj3d.proj_trans_points([edgep_31, edgep_32], renderer.M)
        self.line_outline[1].set_data((pep_aux[0][0], pep_aux[0][1]), (pep_aux[1][0], pep_aux[1][1]))
       
        # 4th axis
        edgep_41 = minmax.copy()
        edgep_42 = edgep_41.copy()
        edgep_42[juggled[1]] = get_flip_min_max(edgep_41, juggled[1], mins, maxs)
        
        pep_aux    = proj3d.proj_trans_points([edgep_41, edgep_42], renderer.M)
        self.line_outline[2].set_data((pep_aux[0][0], pep_aux[0][1]), (pep_aux[1][0], pep_aux[1][1]))
        

        # Ticks
        edgep = [edgep_21, edgep_31, edgep_41]
       

        #isFront = [ highs[tickdir] * face_sign != 1], highs[tickdir] * face_sign != 1, highs[tickdir] * face_sign != 1 ]
        #if (isVisible[1] * face_sign == 1) : self.line_outline[1].draw(renderer)
        #if (isVisible[2] * face_sign == 1) : self.line_outline[2].draw(renderer)
        """
        if isVisible[0]  : self.line_outline[0].draw(renderer)
        if isVisible[1]  : self.line_outline[1].draw(renderer)
        if isVisible[2]  : self.line_outline[2].draw(renderer)
        """
        #self.line_outline[1].draw(renderer)
        #self.line_outline[2].draw(renderer)
        #if ticksign*face_sign == -1 : self.line_outline[2].draw(renderer)

        #for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
        for tick, loc in zip(majorTicks, majorLocs):
            #if tick is None:
            #    continue


            # For outline
            # Get tick line positions
            for i in range(3):
                #if i != 2 : continue 
                if (isVisible[i] * face_sign) != 1 : continue
                self.line_outline[i].draw(renderer)
                # Get tick line positions
                continue
                pos = copy.copy(edgep[i])
                pos[index] = loc
                
                x0, y0, z0 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

                pos[tickdir] = edgep[i][tickdir] + ts[i][0] * info['tick']['inward_factor'] * \
                                                   tickdelta[tickdir]
                x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
                
                tick_update_position(tick, (x0, x1), (y0, y1), (0, 0), False)
                tick.draw(renderer)
                
                pos = copy.copy(edgep[i])
                pos[index] = loc
                
                nt = tickdir + 1
                if nt >2  : nt = 0
                pos[nt] = edgep[i][nt] + ts[i][1] * info['tick']['inward_factor'] * tickdelta[nt]
                x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
                
                tick_update_position(tick, (x0, x2), (y0, y2), (0, 0), False)
                tick.draw(renderer)


        renderer.close_group('axis3d_Outline')
예제 #16
0
    def draw(self, renderer):
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d')

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()
        
        # filter locations here so that no extra grid lines are drawn
        interval = self.get_view_interval()
        majorLocs = [loc for loc in majorLocs if \
                interval[0] < loc < interval[1]]
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [self.major.formatter(val, i)
                       for i, val in enumerate(majorLocs)]

        # Determine bounds
        minx, maxx, miny, maxy, minz, maxz = self.axes.get_w_lims()
        mins = (minx, miny, minz)
        maxs = (maxx, maxy, maxz)
        centers = [(maxv + minv) / 2 for minv, maxv in zip(mins, maxs)]
        deltas = [(maxv - minv) / 12 for minv, maxv in zip(mins, maxs)]
        mins = [minv - delta / 4 for minv, delta in zip(mins, deltas)]
        maxs = [maxv + delta / 4 for maxv, delta in zip(maxs, deltas)]

        # Determine which planes should be visible by the avg z value
        vals = mins[0], maxs[0], mins[1], maxs[1], mins[2], maxs[2]
        tc = self.axes.tunit_cube(vals, renderer.M)
        avgz = [tc[p1][2] + tc[p2][2] + tc[p3][2] + tc[p4][2] for \
                p1, p2, p3, p4 in self._PLANES]
        highs = [avgz[2*i] < avgz[2*i+1] for i in range(3)]

        # Draw plane
        info = self._AXINFO[self.adir]
        index = info['i']
        if not highs[index]:
            plane = self._PLANES[2 * index]
        else:
            plane = self._PLANES[2 * index + 1]
        xys = [tc[p] for p in plane]
        self.set_pane(xys, info['color'])
        self.pane.draw(renderer)

        # Determine grid lines
        minmax = []
        for i, val in enumerate(highs):
            if val:
                minmax.append(maxs[i])
            else:
                minmax.append(mins[i])

        # Draw main axis line
        juggled = art3d.juggle_axes(0, 2, 1, self.adir)
        edgep1 = copy.copy(minmax)
        edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)
        edgep2 = copy.copy(edgep1)
        edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
        pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
        self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
        self.line.draw(renderer)

        # Grid points where the planes meet
        xyz0 = []
        for val in majorLocs:
            coord = copy.copy(minmax)
            coord[index] = val
            xyz0.append(coord)

        # Draw labels
        dy = pep[1][1] - pep[1][0]
        dx = pep[0][1] - pep[0][0]
        lxyz = [(v1 + v2) / 2 for v1, v2 in zip(edgep1, edgep2)]
        labeldeltas = [1.3 * x for x in deltas]
        lxyz = move_from_center(lxyz, centers, labeldeltas)
        tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], \
                renderer.M)
        self.label.set_position((tlx, tly))
        if self.get_rotate_label(self.label.get_text()):
            angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
            self.label.set_rotation(angle)
        self.label.set_va('center')
        self.label.draw(renderer)

        # Grid points at end of one plane
        xyz1 = copy.deepcopy(xyz0)
        newindex = (index + 1) % 3
        newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz1[i][newindex] = newval

        # Grid points at end of the other plane
        xyz2 = copy.deepcopy(xyz0)
        newindex = (index + 2) %  3
        newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz2[i][newindex] = newval

        lines = zip(xyz1, xyz0, xyz2)
        if self.axes._draw_grid:
            self.gridlines.set_segments(lines)
            self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines))
            self.gridlines.draw(renderer, project=True)

        # Draw ticks
        tickdir = info['tickdir']
        tickdelta = deltas[tickdir]
        if highs[tickdir]:
            ticksign = 1
        else:
            ticksign = -1

        for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
            if tick is None:
                continue

            # Get tick line positions
            pos = copy.copy(edgep1)
            pos[index] = loc
            pos[tickdir] = edgep1[tickdir] + 0.1 * ticksign * tickdelta
            x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
            pos[tickdir] = edgep1[tickdir] - 0.2 * ticksign * tickdelta
            x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            # Get position of label
            labeldeltas = [0.6 * x for x in deltas]
            axmask = [True, True, True]
            axmask[index] = False
            pos[tickdir] = edgep1[tickdir]
            pos = move_from_center(pos, centers, labeldeltas, axmask)
            lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
            tick.set_label1(label)
            tick.set_label2(label)
            tick.draw(renderer)

        renderer.close_group('axis3d')
예제 #17
0
파일: axis3d.py 프로젝트: fhelmli/homeNOWG2
    def draw(self, renderer):
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d')

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()

        info = self._axinfo
        index = info['i']

        # filter locations here so that no extra grid lines are drawn
        locmin, locmax = self.get_view_interval()
        if locmin > locmax:
            locmin, locmax = locmax, locmin

        # Rudimentary clipping
        majorLocs = [loc for loc in majorLocs if locmin <= loc <= locmax]
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [
            self.major.formatter(val, i) for i, val in enumerate(majorLocs)
        ]

        mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)

        # Determine grid lines
        minmax = np.where(highs, maxs, mins)

        # Draw main axis line
        juggled = info['juggled']
        edgep1 = minmax.copy()
        edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)

        edgep2 = edgep1.copy()
        edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
        pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
        centpt = proj3d.proj_transform(centers[0], centers[1], centers[2],
                                       renderer.M)
        self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
        self.line.draw(renderer)

        # Grid points where the planes meet
        xyz0 = []
        for val in majorLocs:
            coord = minmax.copy()
            coord[index] = val
            xyz0.append(coord)

        # Draw labels
        peparray = np.asanyarray(pep)
        # The transAxes transform is used because the Text object
        # rotates the text relative to the display coordinate system.
        # Therefore, if we want the labels to remain parallel to the
        # axis regardless of the aspect ratio, we need to convert the
        # edge points of the plane to display coordinates and calculate
        # an angle from that.
        # TODO: Maybe Text objects should handle this themselves?
        dx, dy = (self.axes.transAxes.transform(peparray[0:2, 1]) -
                  self.axes.transAxes.transform(peparray[0:2, 0]))

        lxyz = 0.5 * (edgep1 + edgep2)

        labeldeltas = info['label']['space_factor'] * deltas
        axmask = [True, True, True]
        axmask[index] = False
        lxyz = move_from_center(lxyz, centers, labeldeltas, axmask)
        tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], \
                renderer.M)
        self.label.set_position((tlx, tly))
        if self.get_rotate_label(self.label.get_text()):
            angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
            self.label.set_rotation(angle)
        self.label.set_va(info['label']['va'])
        self.label.set_ha(info['label']['ha'])
        self.label.draw(renderer)

        # Draw Offset text

        # Which of the two edge points do we want to
        # use for locating the offset text?
        if juggled[2] == 2:
            outeredgep = edgep1
            outerindex = 0
        else:
            outeredgep = edgep2
            outerindex = 1

        pos = copy.copy(outeredgep)
        pos = move_from_center(pos, centers, labeldeltas, axmask)
        olx, oly, olz = proj3d.proj_transform(pos[0], pos[1], pos[2],
                                              renderer.M)
        self.offsetText.set_text(self.major.formatter.get_offset())
        self.offsetText.set_position((olx, oly))
        angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
        self.offsetText.set_rotation(angle)
        # Must set rotation mode to "anchor" so that
        # the alignment point is used as the "fulcrum" for rotation.
        self.offsetText.set_rotation_mode('anchor')

        #-----------------------------------------------------------------------
        # Note: the following statement for determining the proper alignment of
        #       the offset text. This was determined entirely by trial-and-error
        #       and should not be in any way considered as "the way".  There are
        #       still some edge cases where alignment is not quite right, but
        #       this seems to be more of a geometry issue (in other words, I
        #       might be using the wrong reference points).
        #
        #   (TT, FF, TF, FT) are the shorthand for the tuple of
        #     (centpt[info['tickdir']] <= peparray[info['tickdir'], outerindex],
        #      centpt[index] <= peparray[index, outerindex])
        #
        #   Three-letters (e.g., TFT, FTT) are short-hand for the array
        #    of bools from the variable 'highs'.
        # ---------------------------------------------------------------------
        if centpt[info['tickdir']] > peparray[info['tickdir'], outerindex]:
            # if FT and if highs has an even number of Trues
            if (centpt[index] <= peparray[index, outerindex]
                    and ((len(highs.nonzero()[0]) % 2) == 0)):
                # Usually, this means align right, except for the FTT case,
                # in which offset for axis 1 and 2 are aligned left.
                if highs.tolist() == [False, True, True] and index in (1, 2):
                    align = 'left'
                else:
                    align = 'right'
            else:
                # The FF case
                align = 'left'
        else:
            # if TF and if highs has an even number of Trues
            if (centpt[index] > peparray[index, outerindex]
                    and ((len(highs.nonzero()[0]) % 2) == 0)):
                # Usually mean align left, except if it is axis 2
                if index == 2:
                    align = 'right'
                else:
                    align = 'left'
            else:
                # The TT case
                align = 'right'

        self.offsetText.set_va('center')
        self.offsetText.set_ha(align)
        self.offsetText.draw(renderer)

        # Draw grid lines
        if len(xyz0) > 0:
            # Grid points at end of one plane
            xyz1 = copy.deepcopy(xyz0)
            newindex = (index + 1) % 3
            newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
            for i in range(len(majorLocs)):
                xyz1[i][newindex] = newval

            # Grid points at end of the other plane
            xyz2 = copy.deepcopy(xyz0)
            newindex = (index + 2) % 3
            newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
            for i in range(len(majorLocs)):
                xyz2[i][newindex] = newval

            lines = zip(xyz1, xyz0, xyz2)
            if self.axes._draw_grid:
                self.gridlines.set_segments(lines)
                self.gridlines.set_color([info['grid']['color']] * len(lines))
                self.gridlines.draw(renderer, project=True)

        # Draw ticks
        tickdir = info['tickdir']
        tickdelta = deltas[tickdir]
        if highs[tickdir]:
            ticksign = 1
        else:
            ticksign = -1

        for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
            if tick is None:
                continue

            # Get tick line positions
            pos = copy.copy(edgep1)
            pos[index] = loc
            pos[tickdir] = edgep1[tickdir] + info['tick']['outward_factor'] * \
                                             ticksign * tickdelta
            x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
            pos[tickdir] = edgep1[tickdir] - info['tick']['inward_factor'] * \
                                             ticksign * tickdelta
            x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            # Get position of label
            labeldeltas = [
                info['ticklabel']['space_factor'] * x for x in deltas
            ]
            axmask = [True, True, True]
            axmask[index] = False
            pos[tickdir] = edgep1[tickdir]
            pos = move_from_center(pos, centers, labeldeltas, axmask)
            lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
            tick.set_label1(label)
            tick.set_label2(label)
            tick.draw(renderer)

        renderer.close_group('axis3d')
예제 #18
0
    def draw(self, renderer):
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d')

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()

        # filter locations here so that no extra grid lines are drawn
        interval = self.get_view_interval()
        majorLocs = [loc for loc in majorLocs if \
                interval[0] < loc < interval[1]]
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [
            self.major.formatter(val, i) for i, val in enumerate(majorLocs)
        ]

        # Determine bounds
        minx, maxx, miny, maxy, minz, maxz = self.axes.get_w_lims()
        mins = np.array((minx, miny, minz))
        maxs = np.array((maxx, maxy, maxz))
        centers = (maxs + mins) / 2.
        deltas = (maxs - mins) / 12.
        mins = mins - deltas / 4.
        maxs = maxs + deltas / 4.

        # Determine which planes should be visible by the avg z value
        vals = mins[0], maxs[0], mins[1], maxs[1], mins[2], maxs[2]
        tc = self.axes.tunit_cube(vals, renderer.M)
        #raise RuntimeError('WTF: p1=%s'%p1)
        avgz = [tc[p1][2] + tc[p2][2] + tc[p3][2] + tc[p4][2] for \
                p1, p2, p3, p4 in self._PLANES]
        highs = np.array([avgz[2 * i] < avgz[2 * i + 1] for i in range(3)])

        # Draw plane
        info = self._AXINFO[self.adir]
        index = info['i']
        if not highs[index]:
            plane = self._PLANES[2 * index]
        else:
            plane = self._PLANES[2 * index + 1]
        xys = [tc[p] for p in plane]
        self.set_pane(xys, info['color'])
        self.pane.draw(renderer)

        # Determine grid lines
        minmax = np.where(highs, maxs, mins)

        # Draw main axis line
        juggled = art3d.juggle_axes(0, 2, 1, self.adir)
        edgep1 = minmax.copy()
        edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)

        edgep2 = edgep1.copy()
        edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
        pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
        self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
        self.line.draw(renderer)

        # Grid points where the planes meet
        xyz0 = []
        for val in majorLocs:
            coord = minmax.copy()
            coord[index] = val
            xyz0.append(coord)

        # Draw labels
        dy = pep[1][1] - pep[1][0]
        dx = pep[0][1] - pep[0][0]

        lxyz = 0.5 * (edgep1 + edgep2)

        labeldeltas = 1.3 * deltas
        lxyz = move_from_center(lxyz, centers, labeldeltas)
        tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], \
                renderer.M)
        self.label.set_position((tlx, tly))
        if self.get_rotate_label(self.label.get_text()):
            angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
            self.label.set_rotation(angle)
        self.label.set_va('center')
        self.label.draw(renderer)

        # Grid points at end of one plane
        xyz1 = copy.deepcopy(xyz0)
        newindex = (index + 1) % 3
        newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz1[i][newindex] = newval

        # Grid points at end of the other plane
        xyz2 = copy.deepcopy(xyz0)
        newindex = (index + 2) % 3
        newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz2[i][newindex] = newval

        lines = zip(xyz1, xyz0, xyz2)
        if self.axes._draw_grid:
            self.gridlines.set_segments(lines)
            self.gridlines.set_color([(0.9, 0.9, 0.9, 1)] * len(lines))
            self.gridlines.draw(renderer, project=True)

        # Draw ticks
        tickdir = info['tickdir']
        tickdelta = deltas[tickdir]
        if highs[tickdir]:
            ticksign = 1
        else:
            ticksign = -1

        for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
            if tick is None:
                continue

            # Get tick line positions
            pos = copy.copy(edgep1)
            pos[index] = loc
            pos[tickdir] = edgep1[tickdir] + 0.1 * ticksign * tickdelta
            x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
            pos[tickdir] = edgep1[tickdir] - 0.2 * ticksign * tickdelta
            x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            # Get position of label
            labeldeltas = [0.6 * x for x in deltas]
            axmask = [True, True, True]
            axmask[index] = False
            pos[tickdir] = edgep1[tickdir]
            pos = move_from_center(pos, centers, labeldeltas, axmask)
            lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
            tick.set_label1(label)
            tick.set_label2(label)
            tick.draw(renderer)

        renderer.close_group('axis3d')
예제 #19
0
    def draw(self, renderer):
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d')

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()

        info = self._axinfo
        index = info['i']

        # filter locations here so that no extra grid lines are drawn
        locmin, locmax = self.get_view_interval()
        if locmin > locmax:
            locmin, locmax = locmax, locmin

        # Rudimentary clipping
        majorLocs = [loc for loc in majorLocs if
                     locmin <= loc <= locmax]
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [self.major.formatter(val, i)
                       for i, val in enumerate(majorLocs)]

        mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)

        # Determine grid lines
        minmax = np.where(highs, maxs, mins)

        # Draw main axis line
        juggled = info['juggled']
        edgep1 = minmax.copy()
        edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)

        edgep2 = edgep1.copy()
        edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
        pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
        centpt = proj3d.proj_transform(centers[0], centers[1], centers[2], renderer.M)
        self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
        self.line.draw(renderer)

        # Grid points where the planes meet
        xyz0 = []
        for val in majorLocs:
            coord = minmax.copy()
            coord[index] = val
            xyz0.append(coord)

        # Draw labels
        peparray = np.asanyarray(pep)
        # The transAxes transform is used because the Text object
        # rotates the text relative to the display coordinate system.
        # Therefore, if we want the labels to remain parallel to the
        # axis regardless of the aspect ratio, we need to convert the
        # edge points of the plane to display coordinates and calculate
        # an angle from that.
        # TODO: Maybe Text objects should handle this themselves?
        dx, dy = (self.axes.transAxes.transform(peparray[0:2, 1]) - 
                  self.axes.transAxes.transform(peparray[0:2, 0]))

        lxyz = 0.5*(edgep1 + edgep2)

        labeldeltas = info['label']['space_factor'] * deltas
        axmask = [True, True, True]
        axmask[index] = False
        lxyz = move_from_center(lxyz, centers, labeldeltas, axmask)
        tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], \
                renderer.M)
        self.label.set_position((tlx, tly))
        if self.get_rotate_label(self.label.get_text()):
            angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
            self.label.set_rotation(angle)
        self.label.set_va(info['label']['va'])
        self.label.set_ha(info['label']['ha'])
        self.label.draw(renderer)


        # Draw Offset text
        
        # Which of the two edge points do we want to
        # use for locating the offset text?
        if juggled[2] == 2 :
            outeredgep = edgep1
            outerindex = 0
        else :
            outeredgep = edgep2
            outerindex = 1

        pos = copy.copy(outeredgep)
        pos = move_from_center(pos, centers, labeldeltas, axmask)
        olx, oly, olz = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M)
        self.offsetText.set_text( self.major.formatter.get_offset() )
        self.offsetText.set_position( (olx, oly) )
        angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
        self.offsetText.set_rotation(angle)
        # Must set rotation mode to "anchor" so that
        # the alignment point is used as the "fulcrum" for rotation.
        self.offsetText.set_rotation_mode('anchor')

        #-----------------------------------------------------------------------
        # Note: the following statement for determining the proper alignment of
        #       the offset text. This was determined entirely by trial-and-error
        #       and should not be in any way considered as "the way".  There are
        #       still some edge cases where alignment is not quite right, but
        #       this seems to be more of a geometry issue (in other words, I
        #       might be using the wrong reference points).
        #
        #   (TT, FF, TF, FT) are the shorthand for the tuple of
        #     (centpt[info['tickdir']] <= peparray[info['tickdir'], outerindex],
        #      centpt[index] <= peparray[index, outerindex])
        #
        #   Three-letters (e.g., TFT, FTT) are short-hand for the array
        #    of bools from the variable 'highs'.
        # ---------------------------------------------------------------------
        if centpt[info['tickdir']] > peparray[info['tickdir'], outerindex] :
            # if FT and if highs has an even number of Trues
            if (centpt[index] <= peparray[index, outerindex]
                and ((len(highs.nonzero()[0]) % 2) == 0)) :
                # Usually, this means align right, except for the FTT case,
                # in which offset for axis 1 and 2 are aligned left.
                if highs.tolist() == [False, True, True] and index in (1, 2) :
                    align = 'left'
                else :
                    align = 'right'
            else :
                # The FF case
                align = 'left'
        else :
            # if TF and if highs has an even number of Trues
            if (centpt[index] > peparray[index, outerindex]
                and ((len(highs.nonzero()[0]) % 2) == 0)) :
                # Usually mean align left, except if it is axis 2
                if index == 2 :
                    align = 'right'
                else :
                    align = 'left'
            else :
                # The TT case
                align = 'right'

        self.offsetText.set_va('center')
        self.offsetText.set_ha(align)
        self.offsetText.draw(renderer)

        # Draw grid lines
        if len(xyz0) > 0:
            # Grid points at end of one plane
            xyz1 = copy.deepcopy(xyz0)
            newindex = (index + 1) % 3
            newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
            for i in range(len(majorLocs)):
                xyz1[i][newindex] = newval

            # Grid points at end of the other plane
            xyz2 = copy.deepcopy(xyz0)
            newindex = (index + 2) %  3
            newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
            for i in range(len(majorLocs)):
                xyz2[i][newindex] = newval

            lines = zip(xyz1, xyz0, xyz2)
            if self.axes._draw_grid:
                self.gridlines.set_segments(lines)
                self.gridlines.set_color([info['grid']['color']] * len(lines))
                self.gridlines.draw(renderer, project=True)

        # Draw ticks
        tickdir = info['tickdir']
        tickdelta = deltas[tickdir]
        if highs[tickdir]:
            ticksign = 1
        else:
            ticksign = -1

        for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
            if tick is None:
                continue

            # Get tick line positions
            pos = copy.copy(edgep1)
            pos[index] = loc
            pos[tickdir] = edgep1[tickdir] + info['tick']['outward_factor'] * \
                                             ticksign * tickdelta
            x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
            pos[tickdir] = edgep1[tickdir] - info['tick']['inward_factor'] * \
                                             ticksign * tickdelta
            x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            # Get position of label
            labeldeltas = [info['ticklabel']['space_factor'] * x for 
                           x in deltas]
            axmask = [True, True, True]
            axmask[index] = False
            pos[tickdir] = edgep1[tickdir]
            pos = move_from_center(pos, centers, labeldeltas, axmask)
            lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
            tick.set_label1(label)
            tick.set_label2(label)
            tick.draw(renderer)

        renderer.close_group('axis3d')
예제 #20
0
    def draw(self, renderer):
        self.label._transform = self.axes.transData
        renderer.open_group('axis3d')

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()

        info = self._AXINFO[self.adir]
        index = info['i']

        # filter locations here so that no extra grid lines are drawn
        interval = self.get_view_interval()
        majorLocs = [loc for loc in majorLocs if \
                interval[0] <= loc <= interval[1]]
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [self.major.formatter(val, i)
                       for i, val in enumerate(majorLocs)]

        mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)

        # Determine grid lines
        minmax = np.where(highs, maxs, mins)

        # Draw main axis line
        juggled = info['juggled']
        edgep1 = minmax.copy()
        edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)

        edgep2 = edgep1.copy()
        edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
        pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
        self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
        self.line.draw(renderer)

        # Grid points where the planes meet
        xyz0 = []
        for val in majorLocs:
            coord = minmax.copy()
            coord[index] = val
            xyz0.append(coord)

        # Draw labels
        peparray = np.asanyarray(pep)
        # The transAxes transform is used because the Text object
        # rotates the text relative to the display coordinate system.
        # Therefore, if we want the labels to remain parallel to the
        # axis regardless of the aspect ratio, we need to convert the
        # edge points of the plane to display coordinates and calculate
        # an angle from that.
        # TODO: Maybe Text objects should handle this themselves?
        dx, dy = (self.axes.transAxes.transform(peparray[0:2, 1]) - 
                  self.axes.transAxes.transform(peparray[0:2, 0]))

        lxyz = 0.5*(edgep1 + edgep2)

        labeldeltas = 1.3 * deltas
        axmask = [True, True, True]
        axmask[index] = False
        lxyz = move_from_center(lxyz, centers, labeldeltas, axmask)
        tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], \
                renderer.M)
        self.label.set_position((tlx, tly))
        if self.get_rotate_label(self.label.get_text()):
            angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
            self.label.set_rotation(angle)
        self.label.set_va('center')
        self.label.set_ha('center')
        self.label.draw(renderer)

        # Grid points at end of one plane
        xyz1 = copy.deepcopy(xyz0)
        newindex = (index + 1) % 3
        newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz1[i][newindex] = newval

        # Grid points at end of the other plane
        xyz2 = copy.deepcopy(xyz0)
        newindex = (index + 2) %  3
        newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz2[i][newindex] = newval

        lines = zip(xyz1, xyz0, xyz2)
        if self.axes._draw_grid:
            self.gridlines.set_segments(lines)
            self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines))
            self.gridlines.draw(renderer, project=True)

        # Draw ticks
        tickdir = info['tickdir']
        tickdelta = deltas[tickdir]
        if highs[tickdir]:
            ticksign = 1
        else:
            ticksign = -1

        for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
            if tick is None:
                continue

            # Get tick line positions
            pos = copy.copy(edgep1)
            pos[index] = loc
            pos[tickdir] = edgep1[tickdir] + 0.1 * ticksign * tickdelta
            x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)
            pos[tickdir] = edgep1[tickdir] - 0.2 * ticksign * tickdelta
            x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            # Get position of label
            labeldeltas = [0.6 * x for x in deltas]
            axmask = [True, True, True]
            axmask[index] = False
            pos[tickdir] = edgep1[tickdir]
            pos = move_from_center(pos, centers, labeldeltas, axmask)
            lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                    renderer.M)

            tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
            tick.set_label1(label)
            tick.set_label2(label)
            tick.draw(renderer)

        renderer.close_group('axis3d')
예제 #21
0
 def draw(self, renderer):
     self.label._transform = self.axes.transData
     renderer.open_group('axis3d')
     majorTicks = self.get_major_ticks()
     majorLocs = self.major.locator()
     interval = self.get_view_interval()
     majorLocs = [loc for loc in majorLocs if \
             interval[0] < loc < interval[1]]
     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()
     mins = np.array((minx, miny, minz))
     maxs = np.array((maxx, maxy, maxz))
     centers = (maxs + mins) / 2.
     deltas = (maxs - mins) / 12.
     mins = mins - deltas / 4.
     maxs = maxs + deltas / 4.
     vals = mins[0], maxs[0], mins[1], maxs[1], mins[2], maxs[2]
     tc = self.axes.tunit_cube(vals, renderer.M)
     avgz = [tc[p1][2] + tc[p2][2] + tc[p3][2] + tc[p4][2] for \
             p1, p2, p3, p4 in self._PLANES]
     highs = np.array([avgz[2*i] < avgz[2*i+1] for i in range(3)])
     info = self._AXINFO[self.adir]
     index = info['i']
     if not highs[index]:
         plane = self._PLANES[2 * index]
     else:
         plane = self._PLANES[2 * index + 1]
     xys = [tc[p] for p in plane]
     self.set_pane(xys, info['color'])
     self.pane.draw(renderer)
     minmax = np.where(highs, maxs, mins)
     juggled = art3d.juggle_axes(0, 2, 1, self.adir)
     edgep1 = minmax.copy()
     edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)
     edgep2 = edgep1.copy()
     edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
     pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
     self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
     self.line.draw(renderer)
     xyz0 = []
     for val in majorLocs:
         coord = minmax.copy()
         coord[index] = val
         xyz0.append(coord)
     dy = pep[1][1] - pep[1][0]
     dx = pep[0][1] - pep[0][0]
     lxyz = 0.5*(edgep1 + edgep2)
     labeldeltas = 1.3 * deltas
     lxyz = move_from_center(lxyz, centers, labeldeltas)
     tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], \
             renderer.M)
     self.label.set_position((tlx, tly))
     if self.get_rotate_label(self.label.get_text()):
         angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
         self.label.set_rotation(angle)
     self.label.set_va('center')
     self.label.draw(renderer)
     xyz1 = copy.deepcopy(xyz0)
     newindex = (index + 1) % 3
     newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
     for i in range(len(majorLocs)):
         xyz1[i][newindex] = newval
     xyz2 = copy.deepcopy(xyz0)
     newindex = (index + 2) %  3
     newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
     for i in range(len(majorLocs)):
         xyz2[i][newindex] = newval
     lines = zip(xyz1, xyz0, xyz2)
     if self.axes._draw_grid:
         self.gridlines.set_segments(lines)
         self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines))
         self.gridlines.draw(renderer, project=True)
     tickdir = info['tickdir']
     tickdelta = deltas[tickdir]
     if highs[tickdir]:
         ticksign = 1
     else:
         ticksign = -1
     for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
         if tick is None:
             continue
         pos = copy.copy(edgep1)
         pos[index] = loc
         pos[tickdir] = edgep1[tickdir] + 0.1 * ticksign * tickdelta
         x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                 renderer.M)
         pos[tickdir] = edgep1[tickdir] - 0.2 * ticksign * tickdelta
         x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                 renderer.M)
         labeldeltas = [0.6 * x for x in deltas]
         axmask = [True, True, True]
         axmask[index] = False
         pos[tickdir] = edgep1[tickdir]
         pos = move_from_center(pos, centers, labeldeltas, axmask)
         lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], \
                 renderer.M)
         tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
         tick.set_label1(label)
         tick.set_label2(label)
         tick.draw(renderer)
     renderer.close_group('axis3d')
예제 #22
0
    def draw(self, renderer):
        self.label._transform = self.axes.transData
        renderer.open_group("axis3d")

        # code from XAxis
        majorTicks = self.get_major_ticks()
        majorLocs = self.major.locator()

        info = self._AXINFO[self.adir]
        index = info["i"]

        # filter locations here so that no extra grid lines are drawn
        interval = self.get_view_interval()
        majorLocs = [loc for loc in majorLocs if interval[0] <= loc <= interval[1]]
        self.major.formatter.set_locs(majorLocs)
        majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)]

        mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)

        # Determine grid lines
        minmax = np.where(highs, maxs, mins)

        # Draw main axis line
        juggled = info["juggled"]
        edgep1 = minmax.copy()
        edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)

        edgep2 = edgep1.copy()
        edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
        pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
        self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
        self.line.draw(renderer)

        # Grid points where the planes meet
        xyz0 = []
        for val in majorLocs:
            coord = minmax.copy()
            coord[index] = val
            xyz0.append(coord)

        # Draw labels
        dy = pep[1][1] - pep[1][0]
        dx = pep[0][1] - pep[0][0]

        lxyz = 0.5 * (edgep1 + edgep2)

        labeldeltas = 1.3 * deltas
        lxyz = move_from_center(lxyz, centers, labeldeltas)
        tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], renderer.M)
        self.label.set_position((tlx, tly))
        if self.get_rotate_label(self.label.get_text()):
            angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
            self.label.set_rotation(angle)
        self.label.set_va("center")
        self.label.draw(renderer)

        # Grid points at end of one plane
        xyz1 = copy.deepcopy(xyz0)
        newindex = (index + 1) % 3
        newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz1[i][newindex] = newval

        # Grid points at end of the other plane
        xyz2 = copy.deepcopy(xyz0)
        newindex = (index + 2) % 3
        newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
        for i in range(len(majorLocs)):
            xyz2[i][newindex] = newval

        lines = zip(xyz1, xyz0, xyz2)
        if self.axes._draw_grid:
            self.gridlines.set_segments(lines)
            self.gridlines.set_color([(0.9, 0.9, 0.9, 1)] * len(lines))
            self.gridlines.draw(renderer, project=True)

        # Draw ticks
        tickdir = info["tickdir"]
        tickdelta = deltas[tickdir]
        if highs[tickdir]:
            ticksign = 1
        else:
            ticksign = -1

        for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
            if tick is None:
                continue

            # Get tick line positions
            pos = copy.copy(edgep1)
            pos[index] = loc
            pos[tickdir] = edgep1[tickdir] + 0.1 * ticksign * tickdelta
            x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M)
            pos[tickdir] = edgep1[tickdir] - 0.2 * ticksign * tickdelta
            x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M)

            # Get position of label
            labeldeltas = [0.6 * x for x in deltas]
            axmask = [True, True, True]
            axmask[index] = False
            pos[tickdir] = edgep1[tickdir]
            pos = move_from_center(pos, centers, labeldeltas, axmask)
            lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M)

            tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
            tick.set_label1(label)
            tick.set_label2(label)
            tick.draw(renderer)

        renderer.close_group("axis3d")