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()