【问题标题】:Limited number of datacursormode on a scatter plot - Matlab散点图上的 datacursormode 数量有限 - Matlab
【发布时间】:2019-10-10 20:08:58
【问题描述】:

我有一个椭圆图(散点图),我希望只有两个数据光标模式,然后得到它们各自的 X 和 Y 坐标。附加的代码绘制了椭圆并标记了一个点,但是我如何限制它并获取坐标?

代码:

clc;
clear;

a=3;  
b=7; 
x0=0;
y0=0;
t=-pi:0.01:pi;
x=x0+a*cos(t);
y=y0+b*sin(t);
sz = 5;
scatter(x,y,sz)

dcm_obj = datacursormode;
set(dcm_obj,'UpdateFcn',@myupdatefcn)

function txt = myupdatefcn(empt,event_obj)
pos1 = get(event_obj,'Position');
txt = {['X position ',num2str(pos1(1))],...
          ['Y position: ',num2str(pos1(2))]};
end    

【问题讨论】:

    标签: matlab


    【解决方案1】:

    您可以使用 while 循环来选择两个点,并使用嵌套函数来共享变量。

    使用嵌套函数是将选定坐标和计数器传递给父函数的一种可能解决方案。

    您可以使用 while 循环将选定(标记)点的数量限制为两个。
    在 while 中放置 pause 对于响应能力很重要。

    这是一个工作代码示例:

    function ellip()
    %Parent function (use a function instead of a script, 
    %allows sharing variables with internal function).
    
    clc;
    %clear;
    
    a=3;  
    b=7; 
    x0=0;
    y0=0;
    t=-pi:0.01:pi;
    x=x0+a*cos(t);
    y=y0+b*sin(t);
    sz = 5;
    h = figure; %Open new figure, and keep the handle.
    scatter(x,y,sz);
    
    dcm_obj = datacursormode;
    dcm_obj.Enable = 'on';
    set(dcm_obj,'UpdateFcn',@myupdatefcn)
    
    %pos_x, pos_y and pos_counter are known both in scope of myupdatefcn and in ellip
    pos_x = zeros(1,2);
    pos_y = zeros(1,2);
    pos_counter = 0;
    
    %Loop until two points are selected
    while (pos_counter < 2) && isvalid(h)
        pause(0.01);
    end
    
    if isvalid(h)
        close(h); %Close the figure;
    
        %Display position of the two selected coordinates.
        fprintf('pos1 = (%f, %f), pos2 = (%f, %f)\n', pos_x(1), pos_y(1), pos_x(2), pos_y(2));
    end
    
    dcm_obj.delete() %Delete the object (cleanup)
    
        %myupdatefcn is a nested function, inside ellip function
        function txt = myupdatefcn(empt, event_obj)      
            pos1 = get(event_obj,'Position');
            txt = {['X position ',num2str(pos1(1))],...
                   ['Y position: ',num2str(pos1(2))]};
            disp(txt);
    
            pos_counter = pos_counter + 1; %Increase counter.
            pos_x(pos_counter) = pos1(1);  %Store position
            pos_y(pos_counter) = pos1(2);        
        end
    
    end
    

    我希望我没听错,很难理解你在问什么......


    更新评论:

    • 在函数外部创建散点图很简单。
    • 保存 4 个位置很简单 - 函数可以返回点数。
    • 我找不到一种优雅的方式将工具提示信息留在绘图上。
      问题是调用createDatatip 会触发事件并多执行几次myupdatefcn
      你可以看看Set data tips programmatically?

    更新代码:

    clc
    clear
    close all
    
    a=3;  
    b=7; 
    x0=0;
    y0=0;
    t=-pi:0.01:pi;
    x=x0+a*cos(t);
    y=y0+b*sin(t);
    sz = 5;
    scatter(x,y,sz);
    
    [pos_x, pos_y] = ellip();
    
    %Display position of the two selected coordinates.
    fprintf('pos1 = (%f, %f), pos2 = (%f, %f)\n', pos_x(1), pos_y(1), pos_x(2), pos_y(2));
    
    
    function [pos_x, pos_y] = ellip()
    %Parent function (use a function instead of a script, 
    %allows sharing variables with internal function).
    
    dcm_obj = datacursormode;
    dcm_obj.Enable = 'on';
    set(dcm_obj,'UpdateFcn',@myupdatefcn)
    
    h = dcm_obj.Figure; %Get hendle to the figure.
    hScatter = findobj(h, 'Type', 'scatter'); %Handle to scatter plot
    
    %pos_x, pos_y and pos_counter are known both in scope of myupdatefcn and in ellip
    pos_x = zeros(1,2);
    pos_y = zeros(1,2);
    pos_counter = 0;
    
    %Loop until two points are selected
    while (pos_counter < 2) && isvalid(h)
        pause(0.01);   
    end
    
    % if isvalid(h)
    %     close(h); %Close the figure;    
    % end
    
    
    %dcm_obj.delete() %Delete the object (cleanup)
    if isvalid(h)
        dcm_obj.Enable = 'off';
        set(dcm_obj,'UpdateFcn',[]) %Replace the callback with an empty function instead of deleting the object
    end
    
        %myupdatefcn is a nested function, inside ellip function
        function txt = myupdatefcn(empt, event_obj)      
            pos1 = get(event_obj,'Position');
    
            txt = {['X position ',num2str(pos1(1))],...
                   ['Y position: ',num2str(pos1(2))]};
    
            if (pos_counter > 0) && (pos_x(pos_counter) == pos1(1)) && (pos_y(pos_counter) == pos1(2))
                return %Return if pod1 is already selected.
            end
    
            disp(txt);
    
            pos_counter = pos_counter + 1; %Increase counter.
            pos_x(pos_counter) = pos1(1);  %Store position
            pos_y(pos_counter) = pos1(2);
    
            %Try keeping the tool-tip data
            hdtip = dcm_obj.createDatatip(hScatter);
            set(hdtip, 'MarkerSize',5, 'MarkerFaceColor','none', 'MarkerEdgeColor','r', 'Marker','o', 'HitTest','off');                    
        end
    end
    

    【讨论】:

    • 酷。该函数是否可能不包含椭圆,因此可以在任何散点图上调用它。如何在绘图上保留数据光标模式属性以及如何保存 4 个位置(2 组 x、y),因为我在工作区中看不到它们。
    • 我在试图保留数据游标模式属性(工具提示)时搞砸了。如果你找到一个优雅的解决方案,请告诉我。
    • 它工作正常,但 datacursormode 将在前两组之后继续工作/标记更多点,尽管 while 循环有限制。反正 pos_x 和 pos_y 会记录前两组。
    • @jane 尝试在末尾添加datacursormode off
    • 谢谢,shell 我将它添加到函数的末尾,在while循环之后?
    猜你喜欢
    • 2012-10-29
    • 2016-06-04
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 2013-02-12
    相关资源
    最近更新 更多