'In Matlab, how to programmatically add datatip to trisurf objects with known vertices index?

Trisurf(f,x,y,z) function can draw a patch object. How can I add datatip to this object at the known vertices index with code?

I tried to use the following codes in 2017b

cursorMode = datacursormode(gcf);
hdtip = cursorMode.createDatatip(h_surf); %h_surf is the handle of trisurf
hdtip.Cursor.Position=pos; %this commond seems cannot find the exact vertex and depends on the view angle, where pos is the vertex coordinates.
hdtip.Cursor.DataIndex=idx; %try to use this command to assign the vertex index, but not successful.DataIndex seems not the vertex index.


Solution 1:[1]

I'll use the trisurf example from the docs to create a mesh:

[x,y] = meshgrid(1:15,1:15);
tri = delaunay(x,y);
z = peaks(15);
h_surf = trisurf(tri,x,y,z);

Now the tri matrix contains the indices within x, y, and z for each vertex in the mesh. We can choose a vertex index idx, and the corresponding value from each of the x/y/z arrays to use as the .Position property of your data cursor. Contrary to your comment, the Position property does not depend on the view angle, it is the position relative to the axes (and therefore your data).

So

idx = 123; % intex within triangulation "tri"
xcurs = x(tri(idx)); % = 5 in this example
ycurs = y(tri(idx)); % = 6 in this example
zcurs = z(tri(idx)); % = 0.65233 in this example
cursorMode = datacursormode(gcf);
hdtip = cursorMode.createDatatip(h_surf); 
hdtip.Cursor.Position = [xcurs,ycurs,zcurs];

You could determine idx however you want, then use a common idx to extract the aligned x, y, and z coordinates.

Two different views to show the data tip stays in place:

plot1

plot2

This example was run using MATLAB R2017b.

Solution 2:[2]

Accordint to @Woffie's suggestions, I tuned a little bit to reproduce the error with different view angle in 2017b and 2019b.

First to enable view([180,0]); line. Run the code to get the correct result. And then without closing the figure,comment this line, only remain view([0,0]); to get the wrong result. But if add Close all to the front of the script, should get the correct result each time. (But still don't know the reason, whether it's a bug or not and how to avoid it smartly.)

It might be good to note, in 2D plots, this usually is not a problem since one doesn't usually change the view.

ngrid=1000;%actualy doesnot matter.
x=linspace(-3,3,ngrid+1);
y=linspace(-3,3,ngrid+1);
[x,y] = meshgrid(x,y);
tri = delaunay(x,y);
z = peaks(x,y);
x=(x+3)/6;y=(y+3)/6;
h_surf = trisurf(tri,x,y,z,'EdgeAlpha',0.1);
x0=0.25;y0=0.44;%the above normlization are not necessary but easier to setup the query node.
z0=z(round(y0*ngrid)+1,round(x0*ngrid)+1);
pos=[x0,y0,z0];
view([0,0]);
view([180,0]); %toggle between these two view angles to see the difference.
cursorMode = datacursormode(gcf);
hdtip = cursorMode.createDatatip(h_surf); 
hdtip.Cursor.Position = pos;
hdtip.Cursor.Position

BTW, I also figured out how to use hdtip.Cursor.DataIndex=idx. Basically, DataIndex here is the linear index for h_surf.XData(or YData or ZData), while the XData, YData, ZData are mxn matrice as the node/vertex coordinates of all faces in h_surf, where m is the number of nodes in each face and n is the number of the faces. So it will be straightforward to convert to node index into DataIndex.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Wolfie
Solution 2