Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d34b8d9

Browse files
daniel-s-ingramQuLogic
authored andcommitted
Add option for text
1 parent 34d3a2d commit d34b8d9

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.patches import Arc
4+
from matplotlib.text import Text
5+
from matplotlib.transforms import IdentityTransform, TransformedBbox, Bbox
6+
7+
8+
class AngleMarker(Arc, Text):
9+
"""
10+
Draws an arc between two vectors which appears circular in display space.
11+
"""
12+
def __init__(self, xy, vec1, vec2, size=100, units="pixels", ax=None,
13+
text='', **kwargs):
14+
"""
15+
Params
16+
------
17+
xy, vec1, vec2 : tuple or array of two floats
18+
center position and two points. Angle marker is drawn between the
19+
two vectors connecting vec1 and vec2 with xy, respectively. Units
20+
are data coordinates.
21+
22+
size : float
23+
diameter of the angle marker in units specified by ``units``.
24+
25+
units : string
26+
One of the following strings to specify the units of ``size``:
27+
* "pixels" : pixels
28+
* "points" : points, use points instead of pixels to not have a
29+
dependence of the dpi
30+
* "axes width", "axes height" : relative units of axes
31+
width, height
32+
* "axes min", "axes max" : minimum or maximum of relative axes
33+
width, height
34+
35+
ax : `matplotlib.axes.Axes`
36+
The axes to add the angle marker to
37+
38+
kwargs :
39+
Further parameters are passed to `matplotlib.patches.Arc`. Use this
40+
to specify, color, linewidth etc of the arc.
41+
42+
"""
43+
self._xydata = xy # in data coordinates
44+
self.ax = ax or plt.gca()
45+
self.vec1 = vec1 # tuple or array of absolute coordinates
46+
self.vec2 = vec2 # tuple or array of absolute coordinates
47+
self.size = size
48+
self.units = units
49+
50+
Arc.__init__(self, self._xydata, size, size, angle=0.0,
51+
theta1=self.theta1, theta2=self.theta2, **kwargs)
52+
Text.__init__(self, x=self._x, y=self._y, text=text, **kwargs)
53+
54+
self.set_transform(IdentityTransform())
55+
self.ax.add_artist(self)
56+
57+
def get_size(self):
58+
factor = 1.
59+
if self.units == "points":
60+
factor = self.ax.figure.dpi / 72.
61+
elif self.units[:4] == "axes":
62+
b = TransformedBbox(Bbox.from_bounds(0, 0, 1, 1),
63+
self.ax.transAxes)
64+
dic = {"max": max(b.width, b.height),
65+
"min": min(b.width, b.height),
66+
"width": b.width, "height": b.height}
67+
factor = dic[self.units[5:]]
68+
return self.size * factor
69+
70+
def set_size(self, size):
71+
self.size = size
72+
73+
def get_center_in_pixels(self):
74+
""" return center in pixels """
75+
return self.ax.transData.transform(self._xydata)
76+
77+
def set_center(self, xy):
78+
""" set center in data coordinates """
79+
self._xydata = xy
80+
81+
def get_theta(self, vec):
82+
vec_in_pixels = self.ax.transData.transform(vec) - self._center
83+
return np.rad2deg(np.arctan2(vec_in_pixels[1], vec_in_pixels[0]))
84+
85+
def get_theta1(self):
86+
return self.get_theta(self.vec1)
87+
88+
def get_theta2(self):
89+
return self.get_theta(self.vec2)
90+
91+
def set_theta(self, angle):
92+
pass
93+
94+
def get_x_text(self):
95+
return self._xydata[0] + 3*self.size
96+
97+
def get_y_text(self):
98+
return self._xydata[1] + 3*self.size
99+
100+
def set_xy_text(self, xy):
101+
pass
102+
103+
def set_color(self, color):
104+
Arc.set_color(self, color)
105+
Text.set_color(self, color)
106+
107+
def draw(self, renderer):
108+
Arc.draw(self, renderer)
109+
Text.draw(self, renderer)
110+
111+
_center = property(get_center_in_pixels, set_center)
112+
theta1 = property(get_theta1, set_theta)
113+
theta2 = property(get_theta2, set_theta)
114+
width = property(get_size, set_size)
115+
height = property(get_size, set_size)
116+
_x = property(get_x_text, set_xy_text)
117+
_y = property(get_y_text, set_xy_text)
118+
119+
120+
fig, ax = plt.subplots()
121+
122+
ax.plot([2, .5, 1], [0, .2, 1])
123+
am = AngleMarker((.5, .2), (2, 0), (1, 1), size=0.25, units="axes max", ax=ax,
124+
text=r"$\theta$")
125+
plt.show()
126+
127+
'''
128+
def testing(size=0.25, units="axes fraction", dpi=100, fs=(6.4, 5),
129+
show=False):
130+
131+
fig, axes = plt.subplots(2, 2, sharex="col", sharey="row", dpi=dpi,
132+
figsize=fs,
133+
gridspec_kw=dict(width_ratios=[1, 3],
134+
height_ratios=[3, 1]))
135+
136+
def plot_angle(ax, pos, vec1, vec2, acol="C0", **kwargs):
137+
ax.plot([vec1[0], pos[0], vec2[0]], [vec1[1], pos[1], vec2[1]],
138+
color=acol)
139+
am = AngleMarker(pos, vec1, vec2, ax=ax, text=r"$\theta$", **kwargs)
140+
141+
tx = "figsize={}, dpi={}, arcsize={} {}".format(fs, dpi, size, units)
142+
axes[0, 1].set_title(tx, loc="right", size=9)
143+
kw = dict(size=size, units=units)
144+
p = (.5, .2), (2, 0), (1, 1)
145+
plot_angle(axes[0, 0], *p, **kw)
146+
plot_angle(axes[0, 1], *p, **kw)
147+
plot_angle(axes[1, 1], *p, **kw)
148+
kw.update(acol="limegreen")
149+
plot_angle(axes[0, 0], (1.2, 0), (1, -1), (1.3, -.8), **kw)
150+
plot_angle(axes[1, 1], (0.2, 1), (0, 0), (.3, .2), **kw)
151+
plot_angle(axes[0, 1], (0.2, 0), (0, -1), (.3, -.8), **kw)
152+
kw.update(acol="crimson")
153+
plot_angle(axes[1, 0], (1, .5), (1, 1), (2, .5), **kw)
154+
155+
fig.tight_layout()
156+
fig.savefig(tx.replace("=", "_") + ".png")
157+
fig.savefig(tx.replace("=", "_") + ".pdf")
158+
if show:
159+
plt.show()
160+
161+
162+
s = [(0.25, "axes min"), (0.25, "axes max"),
163+
(0.25, "axes width"), (0.25, "axes height"),
164+
(100, "pixels"), (72, "points")]
165+
d = [72, 144]
166+
f = [(6.4, 5), (12.8, 10)]
167+
168+
import itertools
169+
170+
for (size, unit), dpi, fs in itertools.product(s, d, f):
171+
testing(size=size, units=unit, dpi=dpi, fs=fs)
172+
'''

0 commit comments

Comments
 (0)