#
# Copyright 2021-2024 konawasabi
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
'''
'''
import numpy as np
from . import math
import tkinter as tk
import re
from kobushi import dialog_multifields
[docs]
class cursor():
def __init__(self,parent):
self.p = parent
[docs]
def point_and_dir(self):
def click_1st(event):
nonlocal pointed_pos,press2nd_id,motion_id
pointerpos.set_data(event.xdata,event.ydata)
pointed_pos = np.array([event.xdata,event.ydata])
self.p.fig_canvas.draw()
self.p.fig_canvas.mpl_disconnect(press1st_id)
press2nd_id = self.p.fig_canvas.mpl_connect('button_press_event',click_2nd)
motion_id = self.p.fig_canvas.mpl_connect('motion_notify_event',motion)
def motion(event):
nonlocal pointed_pos,press2nd_id,motion_id,pointerdir
position = np.array([event.xdata,event.ydata])
vector = (position - pointed_pos)
vector = vector/np.sqrt(np.dot(vector,vector))
if pointerdir == None:
pointerdir = self.p.ax_plane.quiver(event.xdata,event.ydata,vector[0],vector[1],angles='xy',scale=2,scale_units='inches',width=0.0025)
else:
#pointerdir.set_data(event.xdata,event.ydata,vector[0],vector[1])
pointerdir.set_UVC(vector[0],vector[1])
self.p.fig_canvas.draw()
def click_2nd(event):
nonlocal press2nd_id,motion_id
#print(press2nd_id,motion_id)
self.p.fig_canvas.mpl_disconnect(press2nd_id)
self.p.fig_canvas.mpl_disconnect(motion_id)
self.p.drawall()
print('Done')
pointerpos, = self.p.ax_plane.plot([],[],'rx')
pointerdir = None
press1st_id = self.p.fig_canvas.mpl_connect('button_press_event',click_1st)
press2nd_id = None
motion_id = None
pointed_pos = None
[docs]
def distance2pos(self):
def click_1st(event):
nonlocal pointerpos1,pointerpos2,pointed_pos,press1st_id,click_num
if click_num == 0:
pointerpos1.set_data(event.xdata,event.ydata)
pointed_pos = np.array([event.xdata,event.ydata])
self.p.fig_canvas.draw()
print('data pos: ({:.2f},{:.2f})'.format(event.xdata,event.ydata))
click_num +=1
elif click_num == 1:
pointerpos2.set_data(event.xdata,event.ydata)
self.p.fig_canvas.draw()
print('data pos: ({:.2f},{:.2f})'.format(event.xdata,event.ydata))
print(np.sqrt((pointed_pos[0]-event.xdata)**2+(pointed_pos[1]-event.ydata)**2))
click_num +=1
else:
self.p.fig_canvas.mpl_disconnect(press1st_id)
self.p.drawall()
print('Done')
pointerpos1, = self.p.ax_plane.plot([],[],'rx')
pointerpos2, = self.p.ax_plane.plot([],[],'bx')
press1st_id = self.p.fig_canvas.mpl_connect('button_press_event',click_1st)
pointed_pos = None
click_num = 0
[docs]
class marker():
def __init__(self,parent,color):
self.p = parent
self.ax = self.p.parentwindow.ax_plane
self.canvas = self.p.parentwindow.fig_canvas
self.color = color
self.setmarkerobj()
self.prev_trackpos = None
[docs]
def start(self):
self.track_key = self.p.values[3].get()
if self.track_key != '@absolute':
self.track_data = self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result'][:,1:3]
elif '@OWOT_' in self.track_key:
parent_tr = re.search('(?<=@OWOT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
self.track_data = self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result'][:,1:3]
else:
self.track_data = None
self.press_id = self.canvas.mpl_connect('button_press_event',self.press)
self.move_id = self.canvas.mpl_connect('motion_notify_event',self.move)
[docs]
def setpos(self,x,y):
self.markerpos.set_data(x,y)
self.p.values[0].set(x)
self.p.values[1].set(y)
self.p.parent.setdistance()
self.canvas.draw()
[docs]
def move(self,event):
xpos = event.xdata
ypos = event.ydata
if self.track_key == '@absolute':
self.setpos(xpos,ypos)
else:
result = self.nearestpoint(xpos,ypos)
self.setpos(result[1],result[2])
[docs]
def press(self,event):
xpos = event.xdata
ypos = event.ydata
if self.track_key == '@absolute':
self.setpos(xpos,ypos)
else:
result = self.nearestpoint(xpos,ypos)
self.setpos(result[1],result[2])
self.prev_trackpos = result
self.canvas.mpl_disconnect(self.press_id)
self.canvas.mpl_disconnect(self.move_id)
[docs]
def nearestpoint(self,x,y):
inputpos = np.array([x,y])
distance = (self.track_data - inputpos)**2
min_dist_ix = np.argmin(np.sqrt(distance[:,0]+distance[:,1]))
if '@OWOT_' in self.track_key:
parent_tr = re.search('(?<=@OWOT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
return self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result'][min_dist_ix]
else:
return self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result'][min_dist_ix]
[docs]
def setmarkerobj(self,pos=False):
self.markerpos, = self.ax.plot([],[],self.color+'x')
if pos:
self.markerpos.set_data(self.p.values[0].get(),self.p.values[1].get())
[docs]
class arrow():
def __init__(self,parent,marker):
self.p = parent
self.ax = self.p.parentwindow.ax_plane
self.canvas = self.p.parentwindow.fig_canvas
self.marker = marker
self.pointerdir = None
self.tangentline = None
self.lastmousepoint = np.array([0, 0])
[docs]
def start(self):
if self.pointerdir is not None:
self.pointerdir.remove()
self.pointerdir = None
if self.tangentline is not None:
self.tangentline.remove()
self.tangentline = None
self.track_key = self.p.values[3].get()
self.pointed_pos = np.array([self.p.values[0].get(),self.p.values[1].get()])
self.p.parentwindow.sendtopmost()
self.press_id = self.canvas.mpl_connect('button_press_event',self.press)
self.move_id = self.canvas.mpl_connect('motion_notify_event',self.move)
[docs]
def move(self,event):
position = np.array([event.xdata,event.ydata])
if event.xdata is not None and event.ydata is not None:
if self.track_key == '@absolute':
vector = (position - self.pointed_pos)
element = vector/np.sqrt(vector[0]**2+vector[1]**2)
self.lastmousepoint = np.array([event.xdata, event.ydata])
else:
v_marker = (position - self.pointed_pos)
v_track = np.array([np.cos(self.marker.prev_trackpos[4]),np.sin(self.marker.prev_trackpos[4])])
if np.dot(v_marker, v_track) > 0:
vector = v_track
element = vector
else:
vector = np.array([np.cos(self.marker.prev_trackpos[4]-np.pi),np.sin(self.marker.prev_trackpos[4]-np.pi)])
element = vector
self.setobj(element)
if self.track_key == '@absolute':
self.settangent(position)
self.canvas.draw()
sin = vector[1]/np.sqrt(vector[0]**2+vector[1]**2)
cos = vector[0]/np.sqrt(vector[0]**2+vector[1]**2)
theta = np.arccos(cos) if sin > 0 else -np.arccos(cos)
self.p.values[2].set(np.rad2deg(theta))
self.p.values_toshow[2].set('{:.3f}'.format(np.rad2deg(theta)))
self.p.parent.setdistance()
[docs]
def press(self,event):
self.p.parent.printdirection(mycursor=self.p)
self.p.parent.sendtopmost()
self.canvas.mpl_disconnect(self.press_id)
self.canvas.mpl_disconnect(self.move_id)
[docs]
def setobj(self,element,reset=False):
if self.pointerdir == None or reset:
if reset:
self.pointed_pos = np.array([self.p.values[0].get(),self.p.values[1].get()])
element = (np.cos(np.deg2rad(self.p.values[2].get())),np.sin(np.deg2rad(self.p.values[2].get())))
figsize = self.p.parentwindow.fig_plane.get_size_inches()
self.pointerdir = self.ax.quiver(self.pointed_pos[0],self.pointed_pos[1],element[0],element[1],\
angles='xy',scale=2,scale_units='inches',width=0.0025*7/figsize[0])
else:
self.pointerdir.set_UVC(element[0],element[1])
[docs]
def settangent(self,pointerpos,reset=False):
if self.p.values[3].get() == '@absolute':
if reset:
pointerpos = self.lastmousepoint
origin = np.array([self.p.values[0].get(),self.p.values[1].get()])
diff = pointerpos - origin
diagonal = np.dot(math.rotate(np.pi),diff) + origin
if self.tangentline == None or reset:
self.tangentline, = self.ax.plot([diagonal[0],pointerpos[0]],[diagonal[1],pointerpos[1]],'k--',alpha=0.25)
else:
self.tangentline.set_data([diagonal[0],pointerpos[0]],[diagonal[1],pointerpos[1]])
[docs]
def set_direct(self):
if self.pointerdir != None:
self.pointerdir.remove()
self.pointerdir = None
self.setobj(None,reset=True)
#self.p.parent.printdirection()
self.canvas.draw()
[docs]
class marker_simple():
def __init__(self,parent,ax,canvas,color,ch_main,ch_measure,symbol='x'):
self.parent = parent
self.ax = ax
self.canvas = canvas
self.color = color
self.ch_main = ch_main
self.ch_measure = ch_measure
self.symbol = symbol
self.setobj()
def __del__(self):
#self.deleteobj()
pass
[docs]
def start(self,posfunc,pressfunc):
self.posfunc = posfunc
self.pressfunc = pressfunc
self.ch_main()
self.press_id = self.canvas.mpl_connect('button_press_event',self.press)
self.move_id = self.canvas.mpl_connect('motion_notify_event',self.move)
[docs]
def move(self,event):
if event.xdata is not None and event.ydata is not None:
self.setpos(event.xdata,event.ydata)
[docs]
def press(self,event):
if event.xdata is not None and event.ydata is not None:
self.setpos(event.xdata,event.ydata)
self.pressfunc(self)
self.ch_measure()
self.canvas.mpl_disconnect(self.press_id)
self.canvas.mpl_disconnect(self.move_id)
[docs]
def setpos(self,x,y,direct=False):
if direct:
self.xout = x
self.yout = y
else:
self.xout, self.yout = self.posfunc(x,y)
self.markerpos.set_data([self.xout],[self.yout])
#self.annotate.set(text ='({:.1f},{:.1f})'.format(self.xout,self.yout), position=(self.xout,self.yout))
self.canvas.draw()
[docs]
def setobj(self):
if '#' in self.color:
self.markerpos, = self.ax.plot([],[],color=self.color, marker=self.symbol)
else:
self.markerpos, = self.ax.plot([],[],self.color+'x')
#self.annotate = self.ax.text(0,0,'')
[docs]
def deleteobj(self):
marker = self.markerpos
marker.remove()
self.canvas.draw()
[docs]
def setcolor(self,color):
self.markerpos.set_color(color)
self.canvas.draw()
[docs]
class marker_pos():
def __init__(self,parent,color):
self.p = parent
self.ax = self.p.parentwindow.ax_plane
self.canvas = self.p.parentwindow.fig_canvas
self.color = color
self.markerobj = marker_simple(self.p,self.ax,self.canvas,self.color,self.p.parentwindow.sendtopmost,self.p.parent.sendtopmost)
self.markerobj.posfunc = lambda x,y:self.posfunc(x,y)
self.markerobj.pressfunc = lambda p:self.pressfunc(p)
[docs]
def start(self):
self.track_key = self.p.values[3].get()
if '@' not in self.track_key:
self.track_data = self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result'][:,1:3]
elif '@OT_' in self.track_key:
parent_tr = re.search('(?<=@OT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
self.track_data = self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result'][:,1:3]
elif '@KML_' in self.track_key or '@CSV_' in self.track_key:
self.track_data = self.p.parent.mainwindow.trackcontrol.pointsequence_track.track[self.track_key]['result'][:,1:3]
else:
self.track_data = None
self.markerobj.start(lambda x,y:self.posfunc(x,y),lambda p:self.pressfunc(p))
[docs]
def move(self,event):
self.markerobj.move(event)
[docs]
def press(self,event):
self.markerobj.press(event)
[docs]
def nearestpoint(self,x,y):
inputpos = np.array([x,y])
distance = (self.track_data - inputpos)**2
min_dist_ix = np.argmin(np.sqrt(distance[:,0]+distance[:,1]))
if '@' not in self.track_key:
result = self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result'][min_dist_ix]
elif '@OT_' in self.track_key:
parent_tr = re.search('(?<=@OT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
result = self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result'][min_dist_ix]
else:
result = self.p.parent.mainwindow.trackcontrol.pointsequence_track.track[self.track_key]['result'][min_dist_ix]
return result
[docs]
def setmarkerobj(self,pos=False):
self.markerobj.setobj()
if pos:
#self.markerobj.setpos(self.p.values[0].get(),self.p.values[1].get())
self.set_direct(replot=True)
[docs]
def posfunc(self,xpos,ypos):
if self.track_key == '@absolute':
x = xpos
y = ypos
kp = None
else:
result = self.nearestpoint(xpos,ypos)
x = result[1]
y = result[2]
kp = result[0]
self.p.values[0].set(x)
self.p.values[1].set(y)
self.p.values_toshow[0].set('{:.3f}'.format(x))
self.p.values_toshow[1].set('{:.3f}'.format(y))
if kp is not None:
self.p.values[4].set(kp)
self.p.values_toshow[4].set('{:.3f}'.format(kp))
self.p.parent.setdistance()
return x,y
[docs]
def pressfunc(self,parent):
self.p.parent.printdistance(mycursor=self.p)
if self.track_key != '@absolute':
self.prev_trackpos = self.nearestpoint(self.markerobj.xout,self.markerobj.yout)
[docs]
def set_direct(self,replot=False):
self.track_key = self.p.values[3].get()
if self.track_key == '@absolute':
self.track_data = None
kp = None
else:
kp = self.p.values[4].get()
if '@' not in self.track_key:
self.track_data = self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result']
elif '@OT_' in self.track_key:
parent_tr = re.search('(?<=@OT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
self.track_data = self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result']
else:
self.track_data = self.p.parent.mainwindow.trackcontrol.pointsequence_track.track[self.track_key]['result']
pos_kp = []
for i in range(0,5):
if '@' not in self.track_key:
pos_kp.append(math.interpolate_with_dist(self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result'],i,kp))
elif '@OT_' in self.track_key:
parent_tr = re.search('(?<=@OT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
pos_kp.append(math.interpolate_with_dist(self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result'],i,kp))
else:
pos_kp.append(math.interpolate_with_dist(self.p.parent.mainwindow.trackcontrol.pointsequence_track.track[self.track_key]['result'],i,kp))
#pos_kp = self.track_data[self.track_data[:,0] == kp][-1]
if self.p.coordinate_v.get() == 'abs':
offset = np.array([0,0])
offs_angle = 0
else:
offset_input =dialog_multifields.dialog_multifields(self.p.parent.mainwindow,\
[{'name':'x', 'type':'Double', 'label':'x','default':0},\
{'name':'y', 'type':'Double', 'label':'y','default':0},\
{'name':'theta', 'type':'Double', 'label':'theta','default':0}],\
message = 'set offset')
offs_angle =np.deg2rad(float(offset_input.variables['theta'].get()))
offset = np.dot(math.rotate(pos_kp[4]+offs_angle), np.array([float(offset_input.variables['x'].get()), float(offset_input.variables['y'].get())]))
self.p.values[0].set(pos_kp[1]+offset[0])
self.p.values[1].set(pos_kp[2]+offset[1])
self.p.values_toshow[0].set('{:.1f}'.format(pos_kp[1]+offset[0]))
self.p.values_toshow[1].set('{:.1f}'.format(pos_kp[2]+offset[1]))
self.p.values[2].set(np.rad2deg(pos_kp[4]+offs_angle))
self.p.values_toshow[2].set('{:.1f}'.format(np.rad2deg(pos_kp[4]+offs_angle)))
self.prev_trackpos = pos_kp
if '@' not in self.track_key:
self.track_data = self.p.parent.mainwindow.trackcontrol.track[self.track_key]['result'][:1,3]
elif '@OT_' in self.track_key:
parent_tr = re.search('(?<=@OT_).+(?=@)',self.track_key).group(0)
child_tr = self.track_key.split('@_')[-1]
self.track_data = self.p.parent.mainwindow.trackcontrol.track[parent_tr]['othertrack'][child_tr]['result'][:1,3]
else:
self.track_data = self.p.parent.mainwindow.trackcontrol.pointsequence_track.track[self.track_key]['result'][:1,3]
if self.p.coordinate_v.get() != 'abs':
self.track_key = '@absolute'
self.p.values[3].set('@absolute')
self.p.coordinate_v.set('abs')
self.markerobj.setpos(self.p.values[0].get(),self.p.values[1].get(),direct=True)
if not replot:
self.p.parent.setdistance()
#self.p.parent.printdistance()