Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MATLAB-动态更新线句柄的最佳方法';扩展数据和YData?_Matlab_Figures - Fatal编程技术网

MATLAB-动态更新线句柄的最佳方法';扩展数据和YData?

MATLAB-动态更新线句柄的最佳方法';扩展数据和YData?,matlab,figures,Matlab,Figures,我正在收集数据并实时绘制这些数据。数据由运动捕捉系统生成。我有一个类DynamicDataset,它只是一个2列矩阵的包装器(尽管它比这更细微),带有一个用于添加新数据的事件通知程序;另一个类dynamiclotter,用于侦听添加的数据事件并动态更新绘图。适当的代码片段: classdef DynamicDataset < handle properties newestData = []; data = [] end events

我正在收集数据并实时绘制这些数据。数据由运动捕捉系统生成。我有一个类
DynamicDataset
,它只是一个2列矩阵的包装器(尽管它比这更细微),带有一个用于添加新数据的事件通知程序;另一个类
dynamiclotter
,用于侦听添加的数据事件并动态更新绘图。适当的代码片段:

classdef DynamicDataset < handle
    properties
        newestData = [];
        data = []
    end
    events
        DataAdded
    end
    methods
        function append(obj, val)
            obj.data(end+1,:) = val;
            obj.newestData = val;
            notify(obj, 'DataAdded');
        end
    end
end

classdef DynamicPlotter < dynamicprops
    properties
        FH %# figure handle
        AH %# axes handle
        LH %# array of line handles - may have multiple lines on the plot

        dynProps = {} %# cell array of dynamic property names - 
                      %# use to access individual datasets
    end
    methods
        function obj = DynamicPlotter(props) %# props is a cell array of dynamic 
                                             %# properties to store information
            for i = 1:length(props) 
                addprop(obj, props{i});
                obj.(props{i}) = DynamicDataset;
                obj.dynProps = [obj.dynProps props{i}];

                addlistener(obj.(props{i}), 'DataAdded', @obj.updatePlot(i));
            end
            obj.createBlankPlot();
        end

        function createBlankPlot(obj)
            obj.FH = figure;
            obj.AH = axes;

            hold all;

            for i = 1:length(obj.dynProps)
                obj.LH(i) = plot(nan); %# only used to produce a line handle
                    set(obj.LH(i), 'XData', [], 'YData', []);
            end
        end

        function updatePlot(obj, propNum)
            X = get(obj.LH(propNum), 'XData');
            Y = get(obj.LH(propNum), 'YData');

            X(end+1) = obj.(dynProps{propNum}).newestData(1);
            Y(end+1) = obj.(dynProps{propNum}).newestData(2);

            set(obj.LH(propNum), 'XData', X, 'YData', Y);
        end
    end
end
classdef dynamicataset
基于MATLAB代码配置文件,updatePlot()中的set命令相当昂贵。我想知道是否有更好的方法来绘制各个点,因为他们来了?理想情况下,我会将单点推入
XData
YData
并仅绘制该点,但我不知道这是否可行

请注意,可能存在多个lineseries对象(即,同一绘图上的多个图形)<代码> PLOTE()/CODE >将轴句柄作为参数,因此它不考虑先前绘制的行句柄的属性(或者有办法让它这样做吗?);我想做
plot(x,y);持有全部但这会每次给我单独的线句柄,每个对应于一个点

也许没有办法使绘制输入点更快,但我想我会问


编辑:使用我正在使用的实际代码更新OP,而不是使用一个容易被误解的通用示例。

运行代码可能需要很长时间的部分原因是因为您使用for循环来分配变量。根据您使用的Matlab版本的不同,这将显著降低您的过程。我建议使用矢量化为x和y赋值,如下所示:

x = 1:1000;
y = cosd(x);
然后可以指定数据中的第一个点

xi = x(1);
yi = y(1);
打印时,指定XDataSource和YDataSource

h = plot(xi, yi, 'YDataSource', 'yi', 'XDataSource', 'xi');
现在,当您循环更改值时,请使用refreshdata更新扩展数据和Ydata值。使用drawnow函数更新figure窗口

for k = 2:1000,
xi = x(1:k);
yi = y(1:k);
refreshdata(h, 'caller')
drawnow;
end

您在每次更新中处理的数据量很大(尽管实际上只有一个点在更改),这使得您的代码为O(N^2)

通过使用第二个线系列来构建一个大的数据组,可以在将每个点添加到短“活动”线和不经常将大块添加到主线系列之间进行切换。虽然这并不能完全避免O(N^2),但它可以使常数显著减小

如果执行此操作,请记住将“旧”系列和“活动”系列重叠一点,以便它们相互连接

基本上:

    function updatePlot(obj, propNum)
        X = get(obj.LHactive(propNum), 'XData');
        Y = get(obj.LHactive(propNum), 'YData');

        X(end+1) = obj.(dynProps{propNum}).newestData(1);
        Y(end+1) = obj.(dynProps{propNum}).newestData(2);

        if numel(X) > 100
            Xold = [get(obj.LH(propNum), 'XData'); X(2:end)];
            Yold = [get(obj.LH(propNum), 'YData'); Y(2:end)];
            set(obj.LH(propNum), 'XData', Xold, 'YData', Yold);

            X = X(end);
            Y = Y(end);
        end

        set(obj.LHactive(propNum), 'XData', X, 'YData', Y);
    end

您的代码很慢,因为您每次调用updatePlot时都会重新填充所有值。因此,我只会在updatePlot中绘制最新的点(这也是您所说的问题:理想情况下,我会将单个点推入扩展数据和YData并仅绘制该点,但我不知道这是否可行。)

  • 添加属性LH\U点\U计数器

    classdef DynamicPlotter < dynamicprops
       properties
          FH %# figure handle
          AH %# axes handle
          LH %# cell array of line handles - may have multiple lines on the plot
    
          % counter that counts home many points we have for each dynProps
          LH_point_counter = [];
    
          dynProps = {} %# cell array of dynamic property names - 
                  %# use to access individual datasets
       end
    

  • 不幸的是,这不能满足我的需要——我的数据实际上不是在for循环中生成的,而是由运动捕捉系统实时生成的。上面的代码片段只是演示了我正在动态地绘制数据。我将更新OP以反映我的具体情况;我想说得更笼统一些,但我的例子显然是误导性的。我不知道你们是否看到过这一点,但请看一看。基本上,在matlab中使用类通常会导致性能低下,我以前见过这种情况。我的项目需要使用类,因为我不想进入,所以没有任何方法可以解决这个问题。。但是,
    set
    调用是否会因为在方法内部调用而变慢?@strictlyrude27:您应该将addlistener行更正为:
    addlistener(obj.(props{i}),'DataAdded',@(src,ev)obj.updatePlot(i))。您可能还想在
    updatePlot
    function@Amro-哎呀,应该是
    道具
    ,转录错误。用于添加
    @(src,ev
    
    function updatePlot(obj, propNum)
        % plot new point
        new_x = obj.(dynProps{propNum}).newestData(1);
        new_y = obj.(dynProps{propNum}).newestData(2);
        new_handle = plot(new_x, new_y);
    
        % add new handle to list of handles of this property
        counter_this_prop = obj.LH_point_counter(propNum);
        counter_this_prop = counter_this_prop + 1;
        obj.LH{propNum}(counter_this_prop) = new_handle;
    
        % save new counter value
        obj.LH_point_counter(propNum) = counter_this_prop;
    end