Saturday, July 25, 2009

Click selecting a curve

I wanted a nice connection arrow for my app, not just a concatenation of lines like











Recently wxWidgets got cairo and wxPython got it accordingly. Using wxcairo (wx.lib.wxcairo) I could draw a nice line of connection like this.











But there was one problem, in my app, the user needs to be able to select the connection by clicking it. How can I detect if the mouse point is on a connection? I need to calculate the length between the line and the point. cairo uses 3rd order bezier curve. To get the parameter t of the bezier curve that gives the closest point on the curve to the mouse point, I need to differentiate the distance and solve the equation of t (or I can get the condition that on the closest point the tangent vector and the vector towards the mouse point makes the right angle. It should produce the same result). The problem is, the equation is 5th order and I cannot solve it. I thought if I should use numerical calculation but still the calculation cost is too expensive. So I decided to use linear interpolation. It's good as long as the user doesn't recognize the error. I can use bounding box and it won't be time consuming. Finally I decided to divide the curve where t = 0, 0.05, 0.1, 0.15, 0.3, 0.5, 0.7, 0.85, 0.9, 0.95, 1. It should be enough just for a GUI program.


These are several tests.

Divide the curve in 3, 5, 8, and 10













Close up














Final result

No comments: