Hello..
Am having a hard time trying to figure out this problem. I want to catch double left click events created under specific lines that where created by DrawLine().
The idea I have is to create a list with the endpoints of the lines, something like this:
lines = [((Px1, Py1), (Px2, Py2)), ((Px3, Py3), (Px4, Py4)), ((Px5, Py5), (Px6, Py6))....
then iterate over each set of two points, and see if the position of the mouse (x,y) when the double left click event is raised, is in the line created by those 2 points using the slope-point equation.
The thing is that if I have lets say more than 20 lines, I think that the code could be too slow, its there a better way to implement this?
heres the code::.
import wx
from math import sqrt, radians, tan
class MainFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(800, 600))
self.Centre()
wx.EVT_PAINT(self, self.OnPaint)
self.SetBackgroundColour("black")
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_MOTION, self.OnMotion)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
# self.Bind(wx.EVT_ERASE_BACKGROUND,self.OnEraseBackground)
self.Initialize()
def OnEraseBackground(self, evt):
pass
def OnLeftUp(self, evt):
if self.x2 and self.y2:
self.segments.append(((self.x1, self.y1), (self.x2, self.y2)))
self.x1, self.y1 = self.x2, self.y2
else:
self.x1 = False
self.y1 = False
self.x2 = False
self.y2 = False
def OnLeftDown(self, evt):
if evt.LeftDown():
if not self.x1:
self.x1, self.y1 = evt.GetPosition()
def OnMotion(self, evt):
if evt.LeftIsDown():
self.xv, self.yv = evt.GetPosition()
self.x2, self.y2 = self.CalculateSecondPoint(self.xv, self.yv)
self.Refresh(False)
def CalculateSlope(self, x1, y1, x2, y2):
"""Function to calculate the slope of a line given two points
"""
if x1 == x2:
return False
else:
x1 = float(x1)
x2 = float(x2)
y1 = float(y1)
y2 = float(y2)
m = (y2 - y1)/(x2 - x1)
return m
def CalculateSecondPoint(self, xv, yv):
mv = self.CalculateSlope(self.x1, self.y1, xv, yv)
m = False
if self.x1 < xv:
#if the line grows to the right
if tan(radians(300)) < mv <= 0:
#if the virtual line have a slope with an angle between 0 and 60 degrees
m = tan(radians(330))
elif 0 < mv < tan(radians(60)):
#if the virtual line have a slope with an angle between 300 and 0 degrees
m = tan(radians(30))
elif self.x1 > xv:
#if the line grows to the left
if tan(radians(179.9)) < mv < tan(radians(240)):
#if the virtual line have a slope with an angle between 110 and 180 degrees
m = tan(radians(30))
elif tan(radians(120)) < mv < tan(radians(179.9)):
#if the virtual line have a slope with an angle between 180 and 240 degrees
m = tan(radians(150))
if m:
x2, y2 = self.Intersection(self.x1, self.y1, m, xv, yv)
else:
x2 = self.x1
y2 = yv
return x2, y2
def Initialize(self):
self.segments = []
self.x1 = False
self.y1 = False
self.x2 = False
self.y2 = False
def Intersection(self, x1, y1, m, xc, yc):
"""Function to calculate the intersection point of two orthogonal lines
given the slope of one of the line and one point of each line
"""
y2 = (yc + (((y1/m) - x1 + xc)/m))/(1 + (1/(m**2)))
x2 = ((y2 - y1)/m) + x1
return x2, y2
def OnPaint(self, dc):
dc = wx.BufferedPaintDC(self)
self.Draw(dc)
def Draw(self, dc):
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
dc.SetPen(wx.Pen(wx.CYAN, 1))
# dc.DrawSpline(((240, 170), (240, 170), (285, 110)))
if self.x2 and self.y2:
# dc.SetPen(wx.Pen('black', 1))
dc.DrawLine(self.x1, self.y1, self.x2, self.y2)
if len(self.segments) > 0:
for segment in self.segments:
dc.DrawLine(segment[0][0], segment[0][1], segment[1][0], segment[1][1])
class App(wx.App):
def OnInit(self):
frame = MainFrame(None, -1, "test")
frame.Show(True)
return True
if __name__ == "__main__":
app = App()
app.MainLoop()