要点:
canvas的创建方式。
更新数据之后要重新调用canvas.draw,才能刷新绘图板。
import numpy
import matplotlib.pyplot as plt
from shapely.geometry import LineString
def get_rot(angle):
sina = numpy.sin(angle)
cosa = numpy.cos(angle)
ret = numpy.array([[cosa, -sina], [sina, cosa]])
return ret
R1 = get_rot(0.01)
R2 = get_rot(-0.01)
D = 0.02
class Line:
def __init__(self, axes, x,y, fmt='b') -> None:
self.graphic_obj = axes.plot(x,y,fmt)[0]
self.exterior = axes.plot(*self.geo.buffer(0.1).exterior.xy, 'orange')[0]
self.interiors = [axes.plot(*hole.xy, 'orange')[0] for hole in self.geo.buffer(0.1).interiors]
@property
def geo(self):
return LineString(zip(*self.graphic_obj.get_data()))
def update_buffer(self):
self.exterior.set_data(*self.geo.buffer(0.1).exterior.xy)
[x.set_data(*self.geo.buffer(0.1).interiors[idx].xy) for idx,x in enumerate(self.interiors)]
def rot(self, rot):
x, y = self.graphic_obj.get_data()
cx,cy = numpy.mean(x), numpy.mean(y)
xy = numpy.vstack([x-cx, y-cy])
xy = rot.dot(xy)
x = xy[0,:] + cx
y = xy[1,:] + cy
self.graphic_obj.set_data(x,y)
self.update_buffer()
def mv_x(self, dx):
x = self.graphic_obj.get_xdata()
self.graphic_obj.set_xdata(x+dx)
self.update_buffer()
def mv_y(self, dy):
y = self.graphic_obj.get_ydata()
self.graphic_obj.set_ydata(y+dy)
self.update_buffer()
class Form:
def __init__(self) -> None:
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
self.root = tk.Tk()
fig = plt.figure(figsize=(5,4), dpi=100)
self.axes = fig.gca()
print(self.axes)
self.axes.axis([0,4,0,6])
self.axes.set_aspect(1)
self.line = Line(self.axes, [1,2,1.5,1], [1,1,2,1], 'b')
self.ref = Line(self.axes, [1,2,1.5,1], [1,1,2,1], 'r')
self.canvas = FigureCanvasTkAgg(fig, self.root)
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.text = self.axes.text(3,4, str(self.judge(self.line, self.ref)))
self.canvas.draw()
self.root.bind("<Key>", self.action)
self.root.mainloop()
def action(self, event):
c = event.char
print(event, c)
if c == "w":
self.line.mv_y(D)
elif c == "s":
self.line.mv_y(-D)
elif c == "a":
self.line.mv_x(-D)
elif c == "d":
self.line.mv_x(D)
elif c == "q":
self.line.rot(R1)
elif c == "e":
self.line.rot(R2)
ret = self.judge(self.line, self.ref)
self.update_info(str(ret))
self.canvas.draw()
def update_info(self, msg):
self.text.set_text(msg)
@staticmethod
def judge(a, b):
g1 = a.geo.buffer(0.1)
g2 = b.geo.buffer(0.1)
ia = g1.intersection(g2)
ua = g1.union(g2)
iou = ia.area/ ua.area
return iou
Form()