Animated Scatter Plots between two Points at Tkinter Matplotlib Canvas

Viewed 53

I have Tkinter Matplotlib canvas with scatter plot with 2 dots inside a polygon once click the "show polygon" button. As a part of my exercise, I have coded to include 4 intermediate dots once I left-mouse-clicked consecutively one existing dots to other using mouse picker events. However, I would like to do this dynamically and animated, incorporating second point in scatter plot function as the mouse_move(event) coordinates until I click the 2nd existing point. I need animated dots constructed with mouse movements like this Much appreciated your help.

Code is given below:

import numpy as np
import pandas as pd
from pandastable import Table
from shapely.geometry import Polygon
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import ttk as ttk


matplotlib.use('TkAgg')
root = tk.Tk()
root.geometry('700x400')
root.state('zoomed')
df2 = pd.DataFrame({
    'x': [0,100,100,-100,-100,0,],
    'y': [0,0,500,500,0,0,],
})

df= pd.DataFrame()
frame = tk.Frame(root)
frame.place(x=500, y=500)
pt = Table(frame, dataframe=df, width=150,height=400)
pt.show()


def split(start, end, segments):
    #devide linstring to a number of segments and pass only intermidiate points 
    x_delta = (end[0] - start[0]) / float(segments)
    y_delta = (end[1] - start[1]) / float(segments)
    points = [] # pass start and end as well
    for i in range(1, segments):
        points.append([start[0] + i * x_delta, start[1] + i * y_delta])
    return points

class App():
    def __init__(self, master):
        self.master = master
          
        self.points = []
        self.points2 = []
        self.pointSelect = None
        self.dotSelect=None
             
        # Frame 
        self.frame =tk.Frame(master, width=400, height =950,highlightbackground="blue", highlightthickness=5)
        self.frame.place(x=10, y=40)
        

        # button 
        self.button = tk.Button(self.frame,text = "Show Polygon", command=self.plot_section, width =15, height =2 )
        self.button.place (x=30, y=150)     
  
          

        
    def plot_section(self):
        pt.model.df = df2 # writing into pd data frame 
        pt.redraw()
             
        poly_new=list(tuple(map(tuple,np.asarray(df2))))
        print(poly_new)
        polygon2 = Polygon(poly_new)
        self.x,self.y = polygon2.exterior.xy       
        fig.clear()
        ax=fig.add_subplot(111)
        self.x2=(0,50)
        self.y2=(110,110)
        ax.plot(self.x,self.y, color ='blue',picker=True, pickradius=5)
        ax.scatter(self.x2, self.y2, s=32, color ='orange',picker=True)
        canvas.draw_idle()
        
        print(pt.model.df)
               
        def onpick(event):
            if isinstance(event.artist, matplotlib.lines.Line2D):
                thisline = event.artist
                xdata = thisline.get_xdata()
                ydata = thisline.get_ydata()
                ind = event.ind
                print(xdata[ind][0])
                self.points = []
                self.points.append([xdata[ind][0], ydata[ind][0]])
                print('this point click on polygon', self.points)
            

        def onpick2(event):
            print('onpick2', event.artist)

            if isinstance(event.artist, matplotlib.collections.PathCollection):
                index = event.ind
                xy = event.artist.get_offsets()
                print ('hi scatter', xy[index])
                if len(self.points2) == 2:
                    self.points2 = []
                    canvas.draw()
                    self.points.append([xy[index][0][0], xy[index][0][1]])
                    return
                else:
                    self.points2.append([xy[index][0][0], xy[index][0][1]])
                    #print('Selected Coordinates:', self.points2)
                    
                if len(self.points2) == 2:
                    plt.connect('motion_notify_event', mouse_move)
                    # If two points have been selected (a line) then highlight it
                    # (by plotting a red line over it) and call plot reinforcement function
                    cords = self.points2
                    print('hhk',cords)

                    newps=split(cords[0],cords[1],5)
                    x4, y4 = zip(*newps)
                    ax.scatter(x4, y4, c ="blue", s=50)
                    canvas.draw_idle()
                    
                    
            
        def mouse_move(event):
            x, y = event.xdata, event.ydata
            print(x, y)
            

        self.pointSelect=fig.canvas.mpl_connect('pick_event', onpick)
        self.dotSelects=fig.canvas.mpl_connect('pick_event', onpick2)
        

        

fig = Figure(figsize=(8,6), dpi=100)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.RIGHT)

        
app = App(root)
root.mainloop()
0 Answers
Related