 # (no subject)

John Hunter wrote:

"paul" == paul cristini <paul.cristini@...240...> writes:

> The pick method because of the need to click on edges did
> not fullfill my needs. So I wrote a new method Called
> PickBigLine that does not required a mouse click close to
> the edge but close to the line you want to pick. This is
> particularly useful after zooming when the edges are
> sometimes out of the axis limits.

Hi Paul,

It is not clear to me what this method is for. It would help if you
posted an example where the current pick functionality failed and the
one you propose succeeds (perhaps you could define your function at
the top of the file for ease of use).

xt, yt = a.get_transform().numerix_x_y(xdata, ydata)
xt, yt = asarray(xt), asarray(yt)

There is no need to call asarray since numerix_x_y returns arrays.

xc, yc = xt-xt, yt-yt

What is the point of this? Why do you only look at the points xt,
xt, yt, yt? What if someone needs to click on another point
of the line?

if xc==0.0 and yc == 0.0: return 1000000.
D = xc*xc + yc*yc
D1 = -(xt-xywin)*yc+(yt-xywin)*xc
D2 = -(yt-xywin)*yc-(xt-xywin)*xc

What do D1 and D2 represent? I'm having trouble understanding why,
for example, you need to do (xt-xywin)*yc

if D2/D>1.001 or D2/D<-0.001: return 1000000.

I think the 1000000.0 sentinel value should be renamed to some useful
constant name so it will be self documenting.

return abs(D1/D)

artists = self.lines
if not len(artists): return None
ds = [ (dist(a),a) for a in artists]
ds.sort()
return ds

> I also needed to add a
> new property to Line2D called tag (similar to matlab) for
> sorting purposes. I wonder if you have thought of adding
> such a possibility to some objects for which it can be very
> useful.

Does the "label" property help here. Could you give a use case?

Thanks!

JDH

Sorry for the late answer but I had problems in designing a simple example( I
had the very bad idea to letter "l" tas a key to press). Here it is :

from pylab import *

def pick(event):
if event.key=='p' and event.inaxes is not None:
ax=event.inaxes
a=ax.pick(event.x,event.y)
a.set_color('g')
a.set_linewidth(2.)
draw()
if event.key=='m' and event.inaxes is not None:
ax=event.inaxes
a=ax.pickBigLine(event.x,event.y)
a.set_color('g')
a.set_linewidth(2.)
draw()

···

############################################################################
def PlotTwoLines():
# hold(True)
plot([0.,0.],[-100.,100.])
plot([2.,2.],[-1.,1.])
connect('key_press_event',pick)
xmin,xmax,ymin,ymax=axis()
axis([xmin-1.,xmax+1.,ymin*1.1,ymax*1.1])
show()
if __name__=='__main__':
PlotTwoLines()

Two way for picking a line the classical pick method by using the "p"key and
PickBigLine by using the "m" key.
The code just draw two lines a big one and a small one. The classical pick
method works prefectly if you do not zoom to see the small line. But if you do a
zoom
to see more accurately the small line then it is impossible to pick the big line
unless you use PickBigLine.
Basically, PickBigLine evaluates the orthogonal distance from the selected point
to the line by calculating the intersection between the line you want to select
and a line passing through the selected point which is orthogonal.
Here is a modified version of PickBigLine taking into account your remarks and
working with Matplotlib 0.82
--------------------------------------------------------------------------------------------------
def pickBigLine(self, x, y, trans=None):
"""
Return the Line artist under point that is closest to the x, y. if trans
is None, x, and y are in window coords, 0,0 = lower left. Otherwise,
trans is a matplotlib transform that specifies the coordinate system
of x, y.
Calculates the orthogonal distance to the line
Note this algorithm calculates distance to the vertices of the
polygon, so if you want to pick a patch, click on the edge!
"""
if trans is not None:
xywin = trans.xy_tup((x,y))
else:
xywin = x,y

def dist(a):
Cste=1.e6
xdata = a.get_xdata(valid_only = True)
ydata = a.get_ydata(valid_only = True)
# A point is not a line
if len(xdata) == 1: return Cste
xt, yt = a.get_transform().numerix_x_y(xdata, ydata)
xc, yc = xt-xt, yt-yt
if (xc==0.0 and yc == 0.0): return Cste
D = xc*xc + yc*yc
D1 = -(xt-xywin)*yc+(yt-xywin)*xc
D2 = -(yt-xywin)*yc-(xt-xywin)*xc
if D2/D>1.00001 or D2/D<-0.00001: return Cste
return abs(D1/sqrt(D))

artists = self.lines

if not len(artists): return None
ds = [ (dist(a),a) for a in artists]
ds.sort()
return ds
------------------------------------------------------------------------------------

My interests are in ray tracing in geophysics. I am generating a lot of lines
(thousands of) and then I need by zooming to identify trajectories connecting a
source and a receiver. For example when I am picking a line I need to know to
what beam it belongs and also to what ray it coresponds (two integers for
instance). I don't know how to do it with the label property. It is an axes
property not a line2D property.
If you want I can give an example of the use of the tag property I add.

Paul