Matplotlib手绘曲线

时间:2021-7-20 作者:qvyue

Matplotlib手绘曲线

代码:

from matplotlib import pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号




class LineDrawer(object):
    def __init__(self, line, axis, figure): # 将line(Line2D(matplotlib.artist.Artist)作为该类的一个属性,该类只做好数据处理与传递工作

        self.line = line
        self.axis = axis
        self.figure = figure
        
        # 用于拖拽坐标(AxesSubplot(SubplotBase, matplotlib.axes._axes.Axes))
        self.press = None
        self.cur_xlim = None
        self.cur_ylim = None
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.xpress = None
        self.ypress = None

        # 用于将坐标点的存储
        self.lines_x_list = [] # 各分段的总数据
        self.lines_y_list = [] # 各分段的总数据

        # 撤回的回收线段
        self.undo_lines_x_list = []
        self.undo_lines_y_list = []
        
        #self.xs = list(line.get_xdata()) # xs属于自定义变量名
        #self.ys = list(line.get_ydata())
        self.cid_press = self.line.figure.canvas.mpl_connect('button_press_event', self.onPress) # 按下鼠标三键
        self.cid_release = self.line.figure.canvas.mpl_connect('button_release_event', self.onRelease) # 释放鼠标三键
        #self.cid_release = self.line.figure.canvas.mpl_connect('scroll_event', self.zoom_factory) # 滚轮



    def Get_lines_xy_show_From_lines_xy_list(self):
            #print(len(self.lines_x_list), len(self.lines_y_list))
            self.lines_x_show = [] # 取出已经画好的n段曲线
            self.lines_y_show = [] # 取出已经画好的n段曲线
            for l in self.lines_x_list:
                for x in l:
                    self.lines_x_show.append(x)
            for l in self.lines_y_list:
                for y in l:
                    self.lines_y_show.append(y)



    def onPress(self, event):
        if event.button == 3: # 鼠标右键 手绘图
            self.cid_motion = self.figure.canvas.mpl_connect("motion_notify_event", self.mouse_move)

            self.xdata_this_move = []
            self.ydata_this_move = []
            self.Get_lines_xy_show_From_lines_xy_list()


        elif event.button == 2: # 鼠标中键
            if not event.dblclick: #单击鼠标中键 撤回(撤销最后一段)
                try:
                    #print(len(self.lines_x_list), len(self.lines_y_list))
                    self.undo_lines_x_list.append(self.lines_x_list.pop(-1)) # 回收
                    self.undo_lines_y_list.append(self.lines_y_list.pop(-1)) # 回收
                except IndexError:
                    return
            else:#双击鼠标中键 取消撤回
                '''
                try:
                    #print(len(self.lines_x_list), len(self.lines_y_list))
                    self.lines_x_list.append(self.undo_lines_x_list.pop(-1)) # 取消撤回
                    self.lines_y_list.append(self.undo_lines_y_list.pop(-1)) # 取消撤回
                    
                except IndexError:
                    return
                '''
                pass
            self.Get_lines_xy_show_From_lines_xy_list()
            #print(len(self.lines_x_show), len(self.lines_y_show))
            self.line.set_data(self.lines_x_show, self.lines_y_show) # 连接各段,全部画出来
            #self.line.figure.canvas.get_renderer(cleared=True)
            self.line.figure.canvas.draw_idle()



    def mouse_move(self, event):

        self.xdata_this_move.append(event.xdata)
        self.ydata_this_move.append(event.ydata)

        self.lines_x_show.append(event.xdata)
        self.lines_y_show.append(event.ydata)

        self.line.set_data(self.lines_x_show, self.lines_y_show) # 连接各段,全部画出来
        self.line.figure.canvas.draw_idle() # 数据重画


    def onRelease(self, event):
        if event.button == 3: # 鼠标右键 手绘图
            self.cid_release = self.figure.canvas.mpl_disconnect(self.cid_motion)

            self.lines_x_list.append(self.xdata_this_move) # 释放后添加本次运动的x点
            self.lines_y_list.append(self.ydata_this_move) # 释放后添加本次运动的y点

            #print(self.xdata_this_move, self.ydata_this_move, 'n==================nn')


    # 缩放
    def zoom_factory(self, base_scale=1.1):
        # ax (AxesSubplot(SubplotBase, matplotlib.axes._axes.Axes))
        def zoom(event):
            cur_xlim = self.axis.get_xlim()
            cur_ylim = self.axis.get_ylim()

            xdata = event.xdata # get event x location
            ydata = event.ydata # get event y location

            if event.button == 'down':
                # deal with zoom in
                scale_factor = 1 / base_scale
            elif event.button == 'up':
                # deal with zoom out
                scale_factor = base_scale
            else:
                # deal with something that should never happen
                scale_factor = 1
                #print(event.button)

            new_width = (cur_xlim[1] - cur_xlim[0]) * scale_factor
            new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor

            relx = (cur_xlim[1] - xdata)/(cur_xlim[1] - cur_xlim[0])
            rely = (cur_ylim[1] - ydata)/(cur_ylim[1] - cur_ylim[0])

            self.axis.set_xlim([xdata - new_width * (1-relx), xdata + new_width * (relx)])
            self.axis.set_ylim([ydata - new_height * (1-rely), ydata + new_height * (rely)])
            self.axis.figure.canvas.draw() # 数据重画

        #fig = self.axis.get_figure() # get the figure of interest
        self.figure.canvas.mpl_connect('scroll_event', zoom)

        return zoom

    # 左键拖动
    def pan_factory(self):
        def onPress(event):
            if event.button == 1:
                if event.inaxes != self.axis: return
                self.cur_xlim = self.axis.get_xlim()
                self.cur_ylim = self.axis.get_ylim()
                self.press = self.x0, self.y0, event.xdata, event.ydata
                self.x0, self.y0, self.xpress, self.ypress = self.press

        def onRelease(event):
            self.press = None
            self.axis.figure.canvas.draw() # 数据重画

        def onMotion(event):
            if self.press is None: return
            if event.inaxes != self.axis: return
            dx = event.xdata - self.xpress
            dy = event.ydata - self.ypress
            self.cur_xlim -= dx
            self.cur_ylim -= dy
            self.axis.set_xlim(self.cur_xlim)
            self.axis.set_ylim(self.cur_ylim)

            self.axis.figure.canvas.draw() # 数据重画

        #fig = self.axis.get_figure() # get the figure of interest

        # attach the call back
        self.figure.canvas.mpl_connect('button_press_event',onPress)
        self.figure.canvas.mpl_connect('button_release_event',onRelease)
        self.figure.canvas.mpl_connect('motion_notify_event',onMotion)

        #return the function
        return onMotion




def main():
    l = [500, 657, 814, 971, 1128, 1285, 1442, 1599, 1756, 1913, 2070, 1913, 1756, 1599, 1442, 1285, 1128, 971, 814, 657, 500, 1518, 575, 1725, 500]
    X = []
    Y = []
    n = 0
    for i in l:
        for j in range(120):
            n += 1
            X.append(n)
            Y.append(i)


    fig = plt.figure()
    ax = fig.add_subplot(111) # class AxesSubplot(SubplotBase, matplotlib.axes._axes.Axes)
    ax.set_title('Matplotlib手绘曲线')
    line_fix, = ax.plot(X, Y, lw='0.5')
    line_draw_by_hand, = ax.plot([], [], lw=1)
    linebuilder = LineDrawer(line=line_draw_by_hand, axis=ax, figure=fig)
    figZoom = linebuilder.zoom_factory(base_scale = 1.1)
    figPan = linebuilder.pan_factory()
    plt.show()
    # 关闭图像后, 再执行以下代码


    X_line_draw = []
    Y_line_draw = []
    for l in linebuilder.lines_x_list:
        for i in l:
            X_line_draw.append(i)
    for l in linebuilder.lines_y_list:
        for i in l:
            Y_line_draw.append(i)

    out = open('手绘数据.txt', 'w', encoding='utf8')
    for i in range(len(X_line_draw)):
        x = X_line_draw[i]
        y = Y_line_draw[i]
        out.write(f'{x}t{y}n')
    out.close()




if __name__ == '__main__':
    main()







Matplotlib手绘曲线
image-20210325221531635.png

手绘图数据

25.638961693548367  546.1584093872231
36.72397513440853   557.8551871856957
50.580241935483855  563.7035760849321
50.580241935483855  560.7793816353139
50.580241935483855  554.9309927360775
64.43650873655906   563.7035760849321
147.57410954301065  657.2777984727138
216.85544354838703  762.5487986589683
214.084190188172    762.5487986589683
208.5416834677419   756.7004097597319
214.084190188172    791.79074315515
244.56797715053756  891.2133544421681
261.1954973118279   917.5311044887317
261.1954973118279   891.2133544421681
297.2217909946236   867.8197988452226
336.01933803763427  929.2278822872045
358.1893649193547   1025.7262991246043
363.7318716397848   1034.498882473459
380.35939180107505  1008.1811324268953
408.0719254032257   1014.0295213261317
424.69944556451594  1028.6504935742225
546.6345934139782   1163.1634382566588
627.0009408602149   1300.6005773887132
657.4847278225806   1326.9183274352768
660.2559811827956   1312.297355187186
665.7984879032257   1312.297355187186
693.5110215053761   1411.719966474204
723.9948084677418   1502.3699944123675
746.1648353494621   1458.5070776680948
779.4198756720428   1402.9473831253495
796.0473958333331   1423.4167442726766
832.0736895161289   1522.8393555596947
895.812516801075    1654.428105792513
912.4400369623653   1669.0490780406037
915.2112903225803   1651.5039113428948
948.4663306451611   1677.8216613894583
1017.7476646505373  1753.850717079531
1120.2840389784942  1873.7426895138763
1167.3953461021501  1914.6814118085308
1178.4803595430103  1879.5910784131127
1192.3366263440857  1870.818495064258
1220.0491599462362  1917.605606258149
1231.1341733870963  1929.3023840566216
1239.4479334677417  1926.3781896070034
1727.1885248655913  1505.2941888619857
1724.417271505376   1484.8248277146586
1724.417271505376   1478.9764388154222
1735.5022849462362  1473.1280499161858
1763.2148185483866  1493.597411063513
1782.613592069892   1443.886105420004
1824.182392473118   1297.676382939095
1838.0386592741934  1318.1457440864224
1879.6074596774188  1373.7054386291677
1907.3199932795696  1332.7667163345131
1943.3462869623654  1291.8279940398586
1932.2612735215048  1280.131216241386
2084.6802083333328  970.1666045818589
2106.8502352150535  920.4552989383499
2112.3927419354836  917.5311044887317
2156.7327956989243  926.3036878375863
2167.8178091397845  926.3036878375863
2228.785383064516   911.6827155894954
2298.066717069892   891.2133544421681
2300.837970430107   894.1375488917863

主页:https://www.zhihu.com/people/caviar126

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。