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
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")
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')