On Tue, Nov 8, 2011 at 4:50 PM, Alejandro Weinstein <
alejandro.weinst...@gmail.com> wrote:

> Hi:
>
> I am trying to use the event associated to motion_notify_event in a 3D
> plot, and I found that the event does not have the zdata property.
>
> The following code illustrate the problem:
>
> ##################################
> from mpl_toolkits.mplot3d import Axes3D
> import matplotlib.pyplot as plt
>
> def on_hover(event):
>    print dir(event)
>
> fig = plt.figure()
> ax = fig.add_subplot(111, projection='3d')
> x = [1, 2, 3]
> y = [1, 5, 4]
> z = [3, 5, 6]
> ax.scatter(x, y, z)
>
> cid = fig.canvas.mpl_connect('motion_notify_event', on_hover)
>
> plt.show()
> ##################################
>
> When you move the mouse over the figure, you can see the properties of
> event:
>
> ['__doc__', '__init__', '__module__', '__str__',
> '_update_enter_leave', 'button', 'canvas', 'dblclick', 'guiEvent',
> 'inaxes', 'key', 'lastevent', 'name', 'step', 'x', 'xdata', 'y',
> 'ydata']
>
> There is xdata, ydata, but not zdata.
>
> Is zdata missing or should I be using a different event type?
>
> Alejandro.
>
>
Be careful, I don't think the xdata and ydata are in the coordinate system
that you believe they are in.  Because of the way mplot3d works outside of
the proper projections transform framework, it can only guess at what the
3d coordinates are. The x/ydata are probably in the 2d axes coordinates and
not the coordinates that you are using for the 3d axes that is embedded in
the 2d axes, I can't recall for sure.

The following is the function from the Axes3D class used to report a 3d
coordinate that is displayed in the lower-right corner of the figure.  You
might be able to adapt this for your use. Note that self.M is the internal
projection matrix for the Axes3D object.

    def format_coord(self, xd, yd):
        """
        Given the 2D view coordinates attempt to guess a 3D coordinate.
        Looks for the nearest edge to the point and then assumes that
        the point is at the same z location as the nearest point on the
edge.
        """

        if self.M is None:
            return ''

        if self.button_pressed in self._rotate_btn:
            return 'azimuth=%d deg, elevation=%d deg ' % (self.azim,
self.elev)
            # ignore xd and yd and display angles instead

        p = (xd, yd)
        edges = self.tunit_edges()
        #lines = [proj3d.line2d(p0,p1) for (p0,p1) in edges]
        ldists = [(proj3d.line2d_seg_dist(p0, p1, p), i) for \
                i, (p0, p1) in enumerate(edges)]
        ldists.sort()
        # nearest edge
        edgei = ldists[0][1]

        p0, p1 = edges[edgei]

        # scale the z value to match
        x0, y0, z0 = p0
        x1, y1, z1 = p1
        d0 = np.hypot(x0-xd, y0-yd)
        d1 = np.hypot(x1-xd, y1-yd)
        dt = d0+d1
        z = d1/dt * z0 + d0/dt * z1

        x, y, z = proj3d.inv_transform(xd, yd, z, self.M)

        xs = self.format_xdata(x)
        ys = self.format_ydata(y)
        zs = self.format_zdata(z)
        return 'x=%s, y=%s, z=%s' % (xs, ys, zs)

I hope this helps!
Ben Root
------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to