8000 Break axis3d drawing into subfunctions · matplotlib/matplotlib@7762bff · GitHub
[go: up one dir, main page]

Skip to content

Commit 7762bff

Browse files
Break axis3d drawing into subfunctions
1 parent e7fd79f commit 7762bff

File tree

1 file changed

+108
-79
lines changed

1 file changed

+108
-79
lines changed

lib/mpl_toolkits/mplot3d/axis3d.py

Lines changed: 108 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -320,68 +320,63 @@ def draw_pane(self, renderer):
320320

321321
renderer.close_group('pane3d')
322322

323-
@artist.allow_rasterization
324-
def draw(self, renderer):
325-
self.label._transform = self.axes.transData
326-
renderer.open_group("axis3d", gid=self.get_gid())
327-
328-
ticks = self._update_ticks()
329323

330-
# Get general axis information:
324+
def _axmask(self):
331325
info = self._axinfo
332326
index = info["i"]
333-
juggled = info["juggled"]
327+
axmask = [True, True, True]
328+
axmask[index] = False
329+
return axmask
330+
334331

332+
def _draw_ticks(self, renderer, edgep1, deltas_per_point):
335333
mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
334+
ticks = self._update_ticks()
335+
info = self._axinfo
336+
index = info["i"]
336337

337-
minmax = np.where(highs, maxs, mins)
338-
maxmin = np.where(~highs, maxs, mins)
338+
# Draw ticks:
339+
tickdir = self._get_tickdir()
340+
tickdelta = deltas[tickdir] if highs[tickdir] else -deltas[tickdir]
339341

340-
# Create edge points for the black bolded axis line:
341-
edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin)
342+
tick_info = info['tick']
343+
tick_out = tick_info['outward_factor'] * tickdelta
344+
tick_in = tick_info['inward_factor'] * tickdelta
345+
tick_lw = tick_info['linewidth']
346+
edgep1_tickdir = edgep1[tickdir]
347+
out_tickdir = edgep1_tickdir + tick_out
348+
in_tickdir = edgep1_tickdir - tick_in
342349

343-
# Project the edge points along the current position and
344-
# create the line:
345-
pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M)
346-
pep = np.asarray(pep)
347-
self.line.set_data(pep[0], pep[1])
348-
self.line.draw(renderer)
350+
default_label_offset = 8. # A rough estimate
351+
points = deltas_per_point * deltas
352+
for tick in ticks:
353+
# Get tick line positions
354+
pos = edgep1.copy()
355+
pos[index] = tick.get_loc()
356+
pos[tickdir] = out_tickdir
357+
x1, y1, z1 = proj3d.proj_transform(*pos, self.axes.M)
358+
pos[tickdir] = in_tickdir
359+
x2, y2, z2 = proj3d.proj_transform(*pos, self.axes.M)
349360

350-
# Draw labels
351-
# The transAxes transform is used because the Text object
352-
# rotates the text relative to the display coordinate system.
353-
# Therefore, if we want the labels to remain parallel to the
354-
# axis regardless of the aspect ratio, we need to convert the
355-
# edge points of the plane to display coordinates and calculate
356-
# an angle from that.
357-
# TODO: Maybe Text objects should handle this themselves?
358-
dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) -
359-
self.axes.transAxes.transform([pep[0:2, 0]]))[0]
361+
# Get position of label
362+
labeldeltas = (tick.get_pad() + default_label_offset) * points
360363

361-
lxyz = 0.5 * (edgep1 + edgep2)
364+
pos[tickdir] = edgep1_tickdir
365+
pos = _move_from_center(pos, centers, labeldeltas, self._axmask())
366+
lx, ly, lz = proj3d.proj_transform(*pos, self.axes.M)
362367

363-
# A rough estimate; points are ambiguous since 3D plots rotate
364-
reltoinches = self.figure.dpi_scale_trans.inverted()
365-
ax_inches = reltoinches.transform(self.axes.bbox.size)
366-
ax_points_estimate = sum(72. * ax_inches)
367-
deltas_per_point = 48 / ax_points_estimate
368-
default_offset = 21.
369-
labeldeltas = (
370-
(self.labelpad + default_offset) * deltas_per_point * deltas)
371-
axmask = [True, True, True]
372-
axmask[index] = False
373-
lxyz = _move_from_center(lxyz, centers, labeldeltas, axmask)
374-
tlx, tly, tlz = proj3d.proj_transform(*lxyz, self.axes.M)
375-
self.label.set_position((tlx, tly))
376-
if self.get_rotate_label(self.label.get_text()):
377-
angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx)))
378-
self.label.set_rotation(angle)
379-
self.label.set_va(info['label']['va'])
380-
self.label.set_ha(info['label']['ha'])
381-
self.label.set_rotation_mode(info['label']['rotation_mode'])
382-
self.label.draw(renderer)
368+
_tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
369+
tick.tick1line.set_linewidth(tick_lw[tick._major])
370+
tick.draw(renderer)
383371

384-
# Draw Offset text
372+
373+
def _draw_offset_text(self, renderer, edgep1, edgep2, labeldeltas, pep, dx, dy):
374+
mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
375+
376+
# Get general axis information:
377+
info = self._axinfo
378+
index = info["i"]
379+
juggled = info["juggled"]
385380

386381
# Which of the two edge points do we want to
387382
# use for locating the offset text?
@@ -392,7 +387,7 @@ def draw(self, renderer):
392387
outeredgep = edgep2
393388
outerindex = 1
394389

395-
pos = _move_from_center(outeredgep, centers, labeldeltas, axmask)
390+
pos = _move_from_center(outeredgep, centers, labeldeltas, self._axmask())
396391
olx, oly, olz = proj3d.proj_transform(*pos, self.axes.M)
397392
self.offsetText.set_text(self.major.formatter.get_offset())
398393
self.offsetText.set_position((olx, oly))
@@ -445,39 +440,73 @@ def draw(self, renderer):
445440
self.offsetText.set_ha(align)
446441
self.offsetText.draw(renderer)
447442

448-
# Draw ticks:
449-
tickdir = self._get_tickdir()
450-
tickdelta = deltas[tickdir] if highs[tickdir] else -deltas[tickdir]
451443

452-
tick_info = info['tick']
453-
tick_out = tick_info['outward_factor'] * tickdelta
454-
tick_in = tick_info['inward_factor'] * tickdelta
455-
tick_lw = tick_info['linewidth']
456-
edgep1_tickdir = edgep1[tickdir]
457-
out_tickdir = edgep1_tickdir + tick_out
458-
in_tickdir = edgep1_tickdir - tick_in
444+
def _draw_labels(self, renderer, edgep1, edgep2, labeldeltas, dx, dy):
445+
info = self._axinfo
446+
mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
459447

460-
default_label_offset = 8. # A rough estimate
461-
points = deltas_per_point * deltas
462-
for tick in ticks:
463-
# Get tick line positions
464-
pos = edgep1.copy()
465-
pos[index] = tick.get_loc()
466-
pos[tickdir] = out_tickdir
467-
x1, y1, z1 = proj3d.proj_transform(*pos, self.axes.M)
468-
pos[tickdir] = in_tickdir
469-
x2, y2, z2 = proj3d.proj_transform(*pos, self.axes.M)
448+
# Draw labels
449+
lxyz = 0.5 * (edgep1 + edgep2)
450+
lxyz = _move_from_center(lxyz, centers, labeldeltas, self._axmask())
451+
tlx, tly, tlz = proj3d.proj_transform(*lxyz, self.axes.M)
452+
self.label.set_position((tlx, tly))
453+
if self.get_rotate_label(self.label.get_text()):
454+
angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx)))
455+
self.label.set_rotation(angle)
456+
self.label.set_va(info['label']['va'])
457+
self.label.set_ha(info['label']['ha'])
458+
self.label.set_rotation_mode(info['label']['rotation_mode'])
459+
self.label.draw(renderer)
470460

471-
# Get position of label
472-
labeldeltas = (tick.get_pad() + default_label_offset) * points
473461

474-
pos[tickdir] = edgep1_tickdir
475-
pos = _move_from_center(pos, centers, labeldeltas, axmask)
476-
lx, ly, lz = proj3d.proj_transform(*pos, self.axes.M)
462+
@artist.allow_rasterization
463+
def draw(self, renderer):
464+
self.label._transform = self.axes.transData
465+
renderer.open_group("axis3d", gid=self.get_gid())
477466

478-
_tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
479-
tick.tick1line.set_linewidth(tick_lw[tick._major])
480-
tick.draw(renderer)
467+
# Get general axis information:
468+
mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
469+
470+
minmax = np.where(highs, maxs, mins)
471+
maxmin = np.where(~highs, maxs, mins)
472+
473+
# Create edge points for the black bolded axis line:
474+
edgep1, edgep2 = self._get_axis_line_edge_points(minmax, maxmin)
475+
476+
# Draw the lines
477+
# Project the edge points along the current position
478+
pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M)
479+
pep = np.asarray(pep)
480+
self.line.set_data(pep[0], pep[1])
481+
self.line.draw(renderer)
482+
483+
# Calculate offset distances
484+
# A rough estimate; points are ambiguous since 3D plots rotate
485+
reltoinches = self.figure.dpi_scale_trans.inverted()
486+
ax_inches = reltoinches.transform(self.axes.bbox.size)
487+
ax_points_estimate = sum(72. * ax_inches)
488+
deltas_per_point = 48 / ax_points_estimate
489+
default_offset = 21.
490+
labeldeltas = (
491+
(self.labelpad + default_offset) * deltas_per_point * deltas)
492+
# The transAxes transform is used because the Text object
493+
# rotates the text relative to the display coordinate system.
494+
# Therefore, if we want the labels to remain parallel to the
495+
# axis regardless of the aspect ratio, we need to convert the
496+
# edge points of the plane to display coordinates and calculate
497+
# an angle from that.
498+
# TODO: Maybe Text objects should handle this themselves?
499+
dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) -
500+
self.axes.transAxes.transform([pep[0:2, 0]]))[0]
501+
502+
# Draw labels
503+
self._draw_labels(renderer, edgep1, edgep2, labeldeltas, dx, dy)
504+
505+
# Draw Offset text
506+
self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, pep, dx, dy)
507+
508+
# Draw ticks
509+
self._draw_ticks(renderer, edgep1, deltas_per_point)
481510

482511
renderer.close_group('axis3d')
483512
self.stale = False

0 commit comments

Comments
 (0)
0