Skip to content

Commit 0ddae6e

Browse files
authored
Merge pull request #9881 from QuLogic/polar-tick-fixes
Polar tick fixes
2 parents 725d8d6 + 4341f00 commit 0ddae6e

File tree

5 files changed

+3432
-784
lines changed

5 files changed

+3432
-784
lines changed

lib/matplotlib/projections/polar.py

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,9 @@ def _update_padding(self, pad, angle):
328328
def update_position(self, loc):
329329
super(ThetaTick, self).update_position(loc)
330330
axes = self.axes
331-
angle = (loc * axes.get_theta_direction() +
332-
axes.get_theta_offset() - np.pi / 2)
331+
angle = loc * axes.get_theta_direction() + axes.get_theta_offset()
332+
text_angle = np.rad2deg(angle) % 360 - 90
333+
angle -= np.pi / 2
333334

334335
if self.tick1On:
335336
marker = self.tick1line.get_marker()
@@ -354,17 +355,17 @@ def update_position(self, loc):
354355

355356
mode, user_angle = self._labelrotation
356357
if mode == 'default':
357-
angle = 0
358+
text_angle = user_angle
358359
else:
359-
if angle > np.pi / 2:
360-
angle -= np.pi
361-
elif angle < -np.pi / 2:
362-
angle += np.pi
363-
angle = np.rad2deg(angle) + user_angle
360+
if text_angle > 90:
361+
text_angle -= 180
362+
elif text_angle < -90:
363+
text_angle += 180
364+
text_angle += user_angle
364365
if self.label1On:
365-
self.label1.set_rotation(angle)
366+
self.label1.set_rotation(text_angle)
366367
if self.label2On:
367-
self.label2.set_rotation(angle)
368+
self.label2.set_rotation(text_angle)
368369

369370
# This extra padding helps preserve the look from previous releases but
370371
# is also needed because labels are anchored to their center.
@@ -542,17 +543,59 @@ def _get_text2(self):
542543
t.set_rotation_mode('anchor')
543544
return t
544545

545-
def _determine_anchor(self, angle, start):
546-
if start:
547-
if -90 <= angle <= 90:
548-
return 'left', 'center'
546+
def _determine_anchor(self, mode, angle, start):
547+
# Note: angle is the (spine angle - 90) because it's used for the tick
548+
# & text setup, so all numbers below are -90 from (normed) spine angle.
549+
if mode == 'auto':
550+
if start:
551+
if -90 <= angle <= 90:
552+
return 'left', 'center'
553+
else:
554+
return 'right', 'center'
549555
else:
550-
return 'right', 'center'
556+
if -90 <= angle <= 90:
557+
return 'right', 'center'
558+
else:
559+
return 'left', 'center'
551560
else:
552-
if -90 <= angle <= 90:
553-
return 'right', 'center'
561+
if start:
562+
if angle < -68.5:
563+
return 'center', 'top'
564+
elif angle < -23.5:
565+
return 'left', 'top'
566+
elif angle < 22.5:
567+
return 'left', 'center'
568+
elif angle < 67.5:
569+
return 'left', 'bottom'
570+
elif angle < 112.5:
571+
return 'center', 'bottom'
572+
elif angle < 157.5:
573+
return 'right', 'bottom'
574+
elif angle < 202.5:
575+
return 'right', 'center'
576+
elif angle < 247.5:
577+
return 'right', 'top'
578+
else:
579+
return 'center', 'top'
554580
else:
555-
return 'left', 'center'
581+
if angle < -68.5:
582+
return 'center', 'bottom'
583+
elif angle < -23.5:
584+
return 'right', 'bottom'
585+
elif angle < 22.5:
586+
return 'right', 'center'
587+
elif angle < 67.5:
588+
return 'right', 'top'
589+
elif angle < 112.5:
590+
return 'center', 'top'
591+
elif angle < 157.5:
592+
return 'left', 'top'
593+
elif angle < 202.5:
594+
return 'left', 'center'
595+
elif angle < 247.5:
596+
return 'left', 'bottom'
597+
else:
598+
return 'center', 'bottom'
556599

557600
def update_position(self, loc):
558601
super(RadialTick, self).update_position(loc)
@@ -565,7 +608,8 @@ def update_position(self, loc):
565608
full = _is_full_circle_deg(thetamin, thetamax)
566609

567610
if full:
568-
angle = axes.get_rlabel_position() * direction + offset - 90
611+
angle = (axes.get_rlabel_position() * direction +
612+
offset) % 360 - 90
569613
tick_angle = 0
570614
if angle > 90:
571615
text_angle = angle - 180
@@ -574,7 +618,7 @@ def update_position(self, loc):
574618
else:
575619
text_angle = angle
576620
else:
577-
angle = thetamin * direction + offset - 90
621+
angle = (thetamin * direction + offset) % 360 - 90
578622
if direction > 0:
579623
tick_angle = np.deg2rad(angle)
580624
else:
@@ -595,7 +639,7 @@ def update_position(self, loc):
595639
ha = 'left'
596640
va = 'bottom'
597641
else:
598-
ha, va = self._determine_anchor(angle, True)
642+
ha, va = self._determine_anchor(mode, angle, direction > 0)
599643
self.label1.set_ha(ha)
600644
self.label1.set_va(va)
601645
self.label1.set_rotation(text_angle)
@@ -622,7 +666,7 @@ def update_position(self, loc):
622666
self.label2On = False
623667
self.tick2On = False
624668
else:
625-
angle = thetamax * direction + offset - 90
669+
angle = (thetamax * direction + offset) % 360 - 90
626670
if direction > 0:
627671
tick_angle = np.deg2rad(angle)
628672
else:
@@ -639,7 +683,7 @@ def update_position(self, loc):
639683
else:
640684
text_angle = user_angle
641685
if self.label2On:
642-
ha, va = self._determine_anchor(angle, False)
686+
ha, va = self._determine_anchor(mode, angle, direction < 0)
643687
self.label2.set_ha(ha)
644688
self.label2.set_va(va)
645689
self.label2.set_rotation(text_angle)
@@ -932,16 +976,10 @@ def get_xaxis_transform(self, which='grid'):
932976
return self._xaxis_transform
933977

934978
def get_xaxis_text1_transform(self, pad):
935-
if _is_full_circle_rad(*self._realViewLim.intervalx):
936-
return self._xaxis_text_transform, 'center', 'center'
937-
else:
938-
return self._xaxis_text_transform, 'bottom', 'center'
979+
return self._xaxis_text_transform, 'center', 'center'
939980

940981
def get_xaxis_text2_transform(self, pad):
941-
if _is_full_circle_rad(*self._realViewLim.intervalx):
942-
return self._xaxis_text_transform, 'center', 'center'
943-
else:
944-
return self._xaxis_text_transform, 'top', 'center'
982+
return self._xaxis_text_transform, 'center', 'center'
945983

946984
def get_yaxis_transform(self, which='grid'):
947985
if which in ('tick1', 'tick2'):
@@ -1116,10 +1154,6 @@ def set_theta_direction(self, direction):
11161154
raise ValueError(
11171155
"direction must be 1, -1, clockwise or counterclockwise")
11181156
self._direction.invalidate()
1119-
# FIXME: Why is this needed? Even though the tick label gets
1120-
# re-created, the alignment is not correctly updated without a reset.
1121-
self.yaxis.reset_ticks()
1122-
self.yaxis.set_clip_path(self.patch)
11231157

11241158
def get_theta_direction(self):
11251159
"""
@@ -1176,8 +1210,6 @@ def set_rlabel_position(self, value):
11761210
The angular position of the radius labels in degrees.
11771211
"""
11781212
self._r_label_position.clear().translate(np.deg2rad(value), 0.0)
1179-
self.yaxis.reset_ticks()
1180-
self.yaxis.set_clip_path(self.patch)
11811213

11821214
def set_yscale(self, *args, **kwargs):
11831215
Axes.set_yscale(self, *args, **kwargs)
Binary file not shown.

0 commit comments

Comments
 (0)