def draw3d(self, renderer): zs = [self.z for x in self._x] xs,ys,zs = juggle_axes(self._x,self._y,zs,self.dir) xs,ys,zs = proj3d.proj_transform(xs,ys,zs, renderer.M) self._x = xs self._y = ys self.draw2d(renderer)
def draw3d(self, renderer): zs = [self.z for x in self._x] xs, ys, zs = juggle_axes(self._x, self._y, zs, self.dir) xs, ys, zs = proj3d.proj_transform(xs, ys, zs, renderer.M) self._x = xs self._y = ys self.draw2d(renderer)
def draw(self, renderer): x,y = self.get_position() xs,ys,zs = juggle_axes(x,y,self._z,self.dir) xs,ys,zs = proj3d.proj_transform(xs,ys,zs, renderer.M) self.set_x(xs) self.set_y(ys) text.Text.draw(self, renderer) self.set_x(x) self.set_y(y)
def draw(self, renderer): x, y = self.get_position() xs, ys, zs = juggle_axes(x, y, self._z, self.dir) xs, ys, zs = proj3d.proj_transform(xs, ys, zs, renderer.M) self.set_x(xs) self.set_y(ys) text.Text.draw(self, renderer) self.set_x(x) self.set_y(y)
def line_draw(self, renderer): """Draw a 2D line as a 3D line""" oxs, oys = self.get_xdata(), self.get_ydata() xs, ys, zs = juggle_axes(oxs, oys, self.zs, self.dir) xs, ys, zs = proj3d.proj_transform(xs, ys, zs, renderer.M) self._x = xs self._y = ys self.old_draw(renderer) self._x = oxs self._y = oys
def line_draw(self, renderer): """Draw a 2D line as a 3D line""" oxs,oys = self.get_xdata(),self.get_ydata() xs,ys,zs = juggle_axes(oxs,oys,self.zs,self.dir) xs,ys,zs = proj3d.proj_transform(xs,ys,zs, renderer.M) self._x = xs self._y = ys self.old_draw(renderer) self._x = oxs self._y = oys
def patch_draw(self, renderer): orig_offsets = self._offsets xs, ys = zip(*self._offsets) xs, ys, zs = juggle_axes(xs, ys, self.zs, self.dir) xs, ys, zs = proj3d.proj_transform(xs, ys, zs, renderer.M) # mess with colors orig_fcolors = self._facecolors orig_ecolors = self._edgecolors self._facecolors = zalpha(orig_fcolors, zs) self._edgecolors = zalpha(orig_ecolors, zs) self._offsets = zip(xs, ys) self.old_draw(renderer) self._offsets = orig_offsets self._facecolors = orig_fcolors self._edgecolors = orig_ecolors
def patch_draw(self, renderer): orig_offsets = self._offsets xs,ys = zip(*self._offsets) xs,ys,zs = juggle_axes(xs,ys,self.zs,self.dir) xs,ys,zs = proj3d.proj_transform(xs,ys,zs, renderer.M) # mess with colors orig_fcolors = self._facecolors orig_ecolors = self._edgecolors self._facecolors = zalpha(orig_fcolors,zs) self._edgecolors = zalpha(orig_ecolors,zs) self._offsets = zip(xs,ys) self.old_draw(renderer) self._offsets = orig_offsets self._facecolors = orig_fcolors self._edgecolors = orig_ecolors
def draw(self, renderer): xs3d, ys3d, zs3d = self._verts3d xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M) self.set_data(xs, ys) lines.Line2D.draw(self, renderer)
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')
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')
def draw(self, renderer): xs,ys,zs = proj3d.proj_transform(self.xs,self.ys,self.zs, renderer.M) self._x,self._y = xs,ys lines.Line2D.draw(self, renderer)
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')
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')
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')
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')
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')
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")
def draw(self, renderer): xs, ys, zs = proj3d.proj_transform(self.xs, self.ys, self.zs, renderer.M) self._x, self._y = xs, ys lines.Line2D.draw(self, renderer)
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')