How do I draw a number of arbitrary grid lines from data in arrays, independently from the default grid?

4 views (last 30 days)
I'm trying to create a plot with a single diagonal gridline.
I've tried to solve this by myself, and by researching, on a number of occasions, but because of time constraints I've always went the easy way. Here's what I mean:
clc; clear all; close all; format compact; format shortG;
CHCs=(0:0.01:1)';
a=9; % Quantos HPS avaliar?
b=0.5; % HPS mínimo
c=500; % HPS máximo
if a==1
HPS=b
else
r=nthroot(c/b,a-1);
HPS=b*r.^(0:a-1)
end
CHCmedio=CalculaCHCmedioBP(CHCs,HPS);
% Generates strings for legend
LegendString=strings(size(HPS));
for k=1:length(HPS), LegendString(k)=string(sprintf('HPS = %5.3f',HPS(k))); end
% Set figure size in normalized units
f=figure; set(f, 'Units', 'Normalized', 'OuterPosition', [0.25, 0.1, 0.5 ,0.8])
% Plots a diagonal grid line. 'HandleVisibility' 'off' makes the legend
% funcion skip this entry
plot([0,1],[0,1],'--','color',[1 1 1]*223/255,'HandleVisibility','off');
axis([0, 1, 0, 1]); axis square; grid on;
% Plots data
hold on; plot(CHCs,CHCmedio); legend(LegendString,'Location','southeast')
To date, this is my best effort to date at creating an arbitrary grid line. Here's the figure it generates:
This approach has a few problems.
  • The diagonal line can be picked by the legend function. This was compensated for by turning 'HandleVisibility' 'off';
  • The lines' data points can be picked by the data cursor, as shown in the figure.
In a practical sense, this means that I need to compensate for problems I've created by using a workaround, which makes the code more complex than it could be. In a theoretical sense, it's just an incorrect use of the built in functions, because I've plotted the grid line in the same "context" as the data I'm interested in, even though the diagonal grid line shows no relevant data by itself, and is intended to be just a visual aid.
An ideal solution should make this diagonal line just as interactive as the other grid lines (which is, not interactive at all), and not need any form of compensation like the ones I've described, or similiar. And it's also worth pointing out that, while this case shows a very simple custom grid line, it'd be desirable to be able to plot more complex curves (like the actual data) as grid lines, simpliy by adding more data points do the arrays from which the grid lines should be plotted, such as would be possible by the plot approach.
An extended version of this problem is to plot any number of arbitrary grid lines. With the plot approach, this could be done by writing "plot(X,Y)" if you make X a column array of size 'n', and Y a matrix of size 'n' by 'm', to plot 'm' curves.
I know this is something that should be posssible to do, as I remeber using the Nichols chart before in a school project, and that has a very complex grid which is not interactive.

Accepted Answer

dpb
dpb on 5 Jul 2020
The trick used there (Nichols plot and other response plots) is to tag them all when drawing and then them all to be hard for user to find via something like--
GridHandles(1,1) = line(phase, gain, Zlevel(ones(length(gain),1),:), ...
'XlimInclude',LimInclude,'YlimInclude',LimInclude,...
'LineStyle', ':', 'Color', Color, ...
'Parent', ax, 'Tag', 'CSTgridLines', ...
'HandleVisibility', 'off', 'HitTest', 'off');
After drawing with such and setting the handle visibility and hit test properties (jonas got the one right, +1 there! :) ) then they'll not be subject to user interaction.
I would think that would solve your problems pretty well..
  1 Comment
Leonardo Silveira Kiepper
I dug in the documentation for LineProperties, and from what I read and tested, it seems like the two properties jonas pointed will indeed make data points from my grid line unpickable by the data cursor.
The key difference between them is that, while the 'HitTest' property will say who responds to clicks with it's ButtonDownFcn callback, either the line itself or the nearest "ancestor" (I'm not sure what that means, the same as parent in this case, maybe?), the 'PickableParts' property will say if and how the line will capture mouse clicks, with the value 'none' making the line unable to capture mouse clicks regardless of visibility. So I would say that in a more general sense that the 'PickableParts' property is the way to go.
A third issue (admittedly small) I've noticed with the plot approach, which I haven't listed before, is a clipping issue, in which the grid line will be plotted on top of the axes black lines, but this is fixable by plotting black lines on top of the custom grid lines (This isn't a perfect solution though, the horizontal axis gets a bit wonky).
The plot commands that would generate the closest thing to a custom grid line as stated before, while addressing this small quirk, are as such:
% This is the custom grid line
plot([0,1],[0,1],...
'--','color',[1 1 1]*223/255,...
'HandleVisibility','off','PickableParts','none');
% Configure axes
axis([0, 1, 0, 1]); axis square;
% Fix the clipping issue
ax=gca; % Pick the XLim and YLim configured before, instead of copying hard-coded values, for better automation
plot([ax.XLim(1),ax.XLim(1),ax.XLim(2)],[ax.YLim(2),ax.YLim(1),ax.YLim(1)],...
'k','HandleVisibility','off','PickableParts','none');
This does seem to address the practical problems, so I will accept this answer as I believe this workaround will be fine for most applications, mine included (though there may be some other little problem I haven't yet noticed), but it's still a workaround.

Sign in to comment.

More Answers (0)

Categories

Find more on Number games in Help Center and File Exchange

Tags

Products


Release

R2018a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!