matlab - R2014a 或更高版本的 Simulink 中嵌入式 matlab 函数中的图形对象句柄数组

标签 matlab function graphics simulink handle

为了调试,我在 Simulink 的嵌入式 matlab 函数中绘制了一些向量图。在 Matlab R2013b 之前,使用以下最小示例代码一切正常:

function fcn
%#minimum example for plot within for-loop of embedded matlab function

coder.extrinsic('delete');
coder.extrinsic('quiver');
coder.extrinsic('gobjects');
numSteps=4;

persistent hFig;
persistent hVector;

if isempty(hFig)
    hFig = figure;
    hold on;
    hVector=zeros(numSteps,1);
    hVector=gobjects(numSteps,1);
    for i=1:numSteps
        hVector(i) = quiver(0,0,0,0);
    end
end
set(0, 'CurrentFigure', hFig);
delete(hVector);
for i=1:numSteps
    startInc=[1 1;1 1].*i;
    endInc=[2 3;2 -3].*i;
    hVector(i) = quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:));
end

对于句柄数组 hVector,由于在 for 循环中使用,因此需要进行初始化。然而,对于图形句柄对象的初始化,需要函数 gobjects 并且反过来用 zeros(numSteps,1) 进行 double 初始化变得必要,因为 matlab 不能正确确定外部函数输出的数据类型。 正如我所说,如果将此代码片段复制到 simulink 中的嵌入式 matlab 函数 block 而模型中没有任何其他内容,则该代码片段可以正常工作。

我的问题:Mathworks 在 R2014a 中更改了很多绘图函数,其中一项更改是图形句柄的数据类型,对于我的箭袋图,它不是 quiver 类型。因此,使用 zeros(numSteps,1) 进行的初始化会为句柄数组初始化错误的数据类型。但是,由于上述问题,将其保留下来仍然不起作用。 init 循环或任何类似的编译都不会没有错误。

如果您能就此问题提供帮助,我将不胜感激。

最佳答案

您可以尝试删除 gobject 初始化并使用 double() 将您的调用包装到任何 matlab 图形对象。例如:

hVector(i) = double( quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:)) ) ;

我建议阅读 Loren's article关于切换到 HG2 版本的 Matlab 时可能出现的兼容性问题。

它的快速引用更适用于您的问题:

Graphics Functions Return Objects, not Numeric Handles

Prior to R2014b, you could store a set of handles to graphics objects in an array and then add some numeric data to that array. In R2014b, that will cause an error.
[...]
If you find yourself really stuck, it is possible to cast object handles to numeric handles using the double function. You can then cast the number back to an object handle using the handle function. We don't recommend this as a long term solution. Be aware that we may choose to remove this feature in a future version of MATLAB. If we do, we'll let you know in advance.


现在,如果您真的必须使用此解决方案,请注意这两个函数都适用于单个元素,但也适用于数组。所以

hVector_HG  = handle( hVector_Num ) ; %// works if "hVector_Num" is an array of numeric handles
%// and ...
hVector_Num = double( hVector_HG ) ;  %// works if "hVector_HG" is an array of HG2 graphic handles

如果经常需要的话,这可能会简化一种格式或另一种格式之间的往返。


编辑:

我暂时把它放在帖子的底部,因为开头已经是公认的答案,但请尝试以下操作,让我知道它是否有效。它可能会以更好(更具前瞻性)的方式解决您的问题。

另一种初始化给定图形对象句柄数组的方法是创建一个(空的就足够了)并复制它。例如:

hqNaN   = quiver(NaN,NaN) ;                 %// create an empty quiver
hVector = repmat( hqNaN , numSteps , 1 ) ;  %// replicate it in an array

将为您提供一个数组 hVector,其中包含 numSteps HG2 图形对象句柄。此时它们都指向同一个对象,但是用相同类型的句柄覆盖每个元素是完全合法的。所以稍后:

hVector(i) = quiver( ... , etc ... ) ; %// overwrite handle "i" with a new quiver plot handle

将(应该)正常工作。

使用这种方法需要注意的几点:

  • 将在何处创建空箭袋?
    您可能已经有了一个“当前”数字并且您不希望它被弄乱。如果不是,将创建一个新的空图。所以为了确保空箭袋不会造成问题(只是屏幕上的闪烁),你可以这样包装它:

    图; hqNaN = quiver(NaN,NaN) ;关闭(gcf) ;

或者你也可以把它放在一个图形中(它无论如何都是不可见的),以防你需要重新使用这种类型的句柄来进行其他数组初始化。只是不要忘记,一旦关闭图形,或者删除图形对象,hqNaN 变量仍然存在,但它不再是同一类型的句柄(因此不再有用如果您完全想要这种类型,请进行复制)。

  • 如果您不覆盖所有初始句柄数组怎么办?
    请记住,数组的所有初始句柄都指向同一个图形对象。因此,如果您的数组包含 12 个元素,但假设您错误地只覆盖了其中的 10 个,那么 2 个元素将是指向同一对象(您可能已经删除)的句柄)。这意味着调用:
    删除(hVector)
    会让你恼火的:
    使用 handle.handle/delete 时出错。对象无效或已删除。
    gna gna gna ...幸运的是,您可以通过防御性编程并改为使用来轻松地为此做好准备:
    删除(hVector(ishandle(hVector)))
    Matlab 会自动进行检查,只删除正确的句柄。

关于matlab - R2014a 或更高版本的 Simulink 中嵌入式 matlab 函数中的图形对象句柄数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29893283/

相关文章:

matlab - 我的傅里叶级数不符合图表

c# - NUnit 无法找到程序集,但控制台应用程序可以

matlab - 从两个 2 维矩阵创建一个 3 维矩阵

c++ - 如何为模板嵌套类类型的函数声明参数?

javascript - 重构 onload 以添加第二个功能?奖金 : what about adding second functions to variables in general?

c++ - OpenGL 纹理未在模型上正确渲染

android - Unity 法线贴图不适用于 Android 设备

r - 在 R 中放大矩阵

javascript - 使用 facebook connect 触发功能

algorithm - 推荐一些类似于 Bresenham 的二维球面映射算法?