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).I have a couple of questions/comments about your code...

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[1]-xt[0], yt[1]-yt[0]

What is the point of this? Why do you only look at the points xt[1],

xt[0], yt[1], yt[0]? 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[0]-xywin[0])*yc+(yt[0]-xywin[1])*xc

D2 = -(yt[0]-xywin[1])*yc-(xt[0]-xywin[0])*xcWhat do D1 and D2 represent? I'm having trouble understanding why,

for example, you need to do (xt[0]-xywin[0])*ycif 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[0][1]> 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[1]-xt[0], yt[1]-yt[0]

if (xc==0.0 and yc == 0.0): return Cste

D = xc*xc + yc*yc

D1 = -(xt[0]-xywin[0])*yc+(yt[0]-xywin[1])*xc

D2 = -(yt[0]-xywin[1])*yc-(xt[0]-xywin[0])*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[0][1]

------------------------------------------------------------------------------------

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