| 571 | |
| 572 | @artist.allow_rasterization |
| 573 | def draw(self, renderer): |
| 574 | self.label._transform = self.axes.transData |
| 575 | self.offsetText._transform = self.axes.transData |
| 576 | renderer.open_group("axis3d", gid=self.get_gid()) |
| 577 | |
| 578 | # Get general axis information: |
| 579 | mins, maxs, tc, highs = self._get_coord_info() |
| 580 | centers, deltas = self._calc_centers_deltas(maxs, mins) |
| 581 | |
| 582 | # Calculate offset distances |
| 583 | # A rough estimate; points are ambiguous since 3D plots rotate |
| 584 | reltoinches = self.get_figure(root=False).dpi_scale_trans.inverted() |
| 585 | ax_inches = reltoinches.transform(self.axes.bbox.size) |
| 586 | ax_points_estimate = sum(72. * ax_inches) |
| 587 | deltas_per_point = 48 / ax_points_estimate |
| 588 | default_offset = 21. |
| 589 | labeldeltas = (self.labelpad + default_offset) * deltas_per_point * deltas |
| 590 | |
| 591 | # Determine edge points for the axis lines |
| 592 | minmax = np.where(highs, maxs, mins) # "origin" point |
| 593 | maxmin = np.where(~highs, maxs, mins) # "opposite" corner near camera |
| 594 | |
| 595 | for edgep1, edgep2, pos in zip(*self._get_all_axis_line_edge_points( |
| 596 | minmax, maxmin, self._tick_position)): |
| 597 | # Project the edge points along the current position |
| 598 | pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) |
| 599 | pep = np.asarray(pep) |
| 600 | |
| 601 | # The transAxes transform is used because the Text object |
| 602 | # rotates the text relative to the display coordinate system. |
| 603 | # Therefore, if we want the labels to remain parallel to the |
| 604 | # axis regardless of the aspect ratio, we need to convert the |
| 605 | # edge points of the plane to display coordinates and calculate |
| 606 | # an angle from that. |
| 607 | # TODO: Maybe Text objects should handle this themselves? |
| 608 | dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - |
| 609 | self.axes.transAxes.transform([pep[0:2, 0]]))[0] |
| 610 | |
| 611 | # Draw the lines |
| 612 | self.line.set_data(pep[0], pep[1]) |
| 613 | self.line.draw(renderer) |
| 614 | |
| 615 | # Draw ticks |
| 616 | self._draw_ticks(renderer, edgep1, centers, deltas, highs, |
| 617 | deltas_per_point, pos) |
| 618 | |
| 619 | # Draw Offset text |
| 620 | self._draw_offset_text(renderer, edgep1, edgep2, labeldeltas, |
| 621 | centers, highs, pep, dx, dy) |
| 622 | |
| 623 | for edgep1, edgep2, pos in zip(*self._get_all_axis_line_edge_points( |
| 624 | minmax, maxmin, self._label_position)): |
| 625 | # See comments above |
| 626 | pep = proj3d._proj_trans_points([edgep1, edgep2], self.axes.M) |
| 627 | pep = np.asarray(pep) |
| 628 | dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) - |
| 629 | self.axes.transAxes.transform([pep[0:2, 0]]))[0] |
| 630 | |