使用回调来识别 3D 绘图上的鼠标选定点,有时只能在另一个 m 文件中作为函数使用,为什么?

问题描述 投票:0回答:1

在处理“识别 3D 绘图上的鼠标选定点”问题时,建议使用回调函数来保留绘图上的交互焦点并选择/识别任意数量的点,我遇到了以下奇怪的行为.

唯一错误地使用欧几里德计算的 Matlab“答案”,因此我将其改编为 for Octave 并且我在这里提供了一个更好的 3-D 最小面积解决方案作为完整代码。

我无法弄清楚的是,当我尝试将代码复制到模糊逻辑文件(非功能性的 m 文件)时,它无法工作,并在

Pt = get(handle.a, "CurrentPoint")
==>“句柄无法识别..”处抛出错误。 。” 我将
handle.a=axes
声明放在哪里并不重要。

这里提供的版本与 M 文件作为函数或不一样工作,但是一旦我将它放入包含其他代码的文件中,而不仅仅是简单的向量语句,如果主文件不是“函数”,它就会失败-m-文件”

我纯粹是猜测工作,并将“函数”添加到文件顶部并保存它,有人可以解释为什么吗?

function Interactive_surf

format short;
handle.a = axes;

Xt = [0 0.71429 1.4286  2.1429  2.8571  3.5714  4.2857  5   5.7143  6.4286  7.1429  7.8571  8.5714  9.2857  10];
Yt = [0 0.71429 1.4286  2.1429  2.8571  3.5714  4.2857  5   5.7143  6.4286  7.1429  7.8571  8.5714  9.2857  10];
Z = [ 6.2518    6.4574  7.0428  8.1286  9.3374  10.149  10.435  10.462  10.435  10.531  11.293  12.839  14.343  14.955  15;
      7.0713    7.2578  7.7689  8.7243  9.7992  10.528  10.786  10.81   10.786  10.542  11.306  12.856  14.362  14.971  15.015;
      8.2585    8.432   9.0076  9.789   10.672  11.272  11.486  11.506  11.486  11.272  11.516  13.118  14.652  15.218  15.247;
      9.7942    9.9353  10.715  12.178  12.698  13.041  13.161  13.172  13.161  13.041  12.698  14.456  16.12   16.419  16.386;
      11.446    11.556  12.295  14.137  16.275  16.06   15.987  15.98   15.987  16.06   16.275  17.449  19.288  18.78   18.699;
      12.902    12.988  13.682  15.392  17.287  18.291  18.598  18.572  18.598  18.877  19.709  21.084  22.69   21.138  21.166;
      13.936    14.007  14.664  16.27   17.992  18.872  19.229  19.401  19.481  19.815  20.77   22.286  23.469  22.158  22.181;
      14.532    14.594  15.229  16.77   18.394  19.207  19.537  19.703  19.781  20.116  21.061  22.519  23.532  22.807  22.827;
      14.819    14.878  15.5    17.01   18.586  19.368  19.686  19.848  19.925  20.26   21.198  22.625  23.602  23.454  23.469;
      14.937    14.993  15.611  17.108  18.665  19.434  19.747  19.907  19.984  20.319  21.253  22.667  23.962  24.001  24.011;
      14.979    15.035  15.652  17.143  18.694  19.457  19.769  19.929  20.005  20.34   21.273  22.682  23.97   24.394  24.396;
      14.995    15.051  15.667  17.157  18.704  19.466  19.777  19.937  20.013  20.348  21.281  22.688  23.973  24.651  24.651;
      15    15.056  15.671  17.161  18.707  19.469  19.78   19.939  20.016  20.351  21.283  22.69   23.974  24.674  24.803;
      15    15.056  15.671  17.161  18.707  19.469  19.78   19.939  20.016  20.351  21.283  22.69   23.974  24.674  24.89;
      15    15.056  15.671  17.161  18.707  19.469  19.78   19.939  20.016  20.351  21.283  22.69   23.974  24.674  24.922];

## Assign raw data to the handle structure
handle.x = Xt;
handle.y = Yt;
handle.z = Z;   ## NOTE the Z-matrix has columns as X-axisvalues and


###  Plot in 3D with CallBack function called
handle.p = surf(handle.x,handle.y,handle.z, 'ButtonDownFcn', {@click});
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
grid on

function click(src,~)
    ## Get current perpendicular screen vector
    Pt = get(handle.a, "CurrentPoint")

    ###  Sort through every point in the surface to find the smallest Area to the point
    for dy= 1:15
      for dx = 1:15
        surf_Pt(dx, :) = [handle.x(dx) handle.y(dy) handle.z(dy, dx)];

        v1 = surf_Pt(dx, :) - Pt(1,:);         ## Position vectors: line vector end point to
        v2 = surf_Pt(dx, :) - Pt(2,:);         ## existing surface grid points
        X_Prod = cross(v1, v2);               ## Vector Cross product gives normal vector
        Mag_X_Prod = norm(X_Prod);            ## |normal vector|==> Area of //pipehead
        Area(dx, dy)  = 0.5*Mag_X_Prod;       ## Store each area of triangle
      endfor
    endfor

    [row, col] = find(Area == min(Area(:)))
    str = 'min_Area = %d';
    str1 = sprintf(str, Area(row, col));
    disp(str1)

    # Display the selected point on 3D plot.
    # Points on the fence may not generate a label,
    # so rotate the image so as it shows inside the grid, then click.
    
    formatSpec = "Pt clicked = [%d %d %d]";
    point_text_val = [handle.x(row) handle.y(col) handle.z(col, row)];
    pos_text_z = (handle.z(col, row))+0.2;
    str = sprintf(formatSpec, point_text_val)
    text(handle.x(row), handle.y(col), pos_text_z, str,'FontSize',18)

    ## NOTES
    ## The figure properties "alphamap" would be used to modify the transparency
    ## of the axes frame and allow visiblity of the labels added above that
    ## run off behind the 100%-white fence SADLY
    ##  "Transparency is not yet implemented for figure objects. alphamap is unused"


endfunction


end
callback octave
1个回答
0
投票

在发布的代码中,

click
是一个嵌套函数。作为嵌套函数,它可以访问父函数中定义的变量。

如果删除文件顶部的

function
行,则M文件是一个脚本,并且函数
click
是一个本地函数。作为局部函数,它无权访问在其外部定义的变量。在函数之前或之后的脚本中定义的任何变量在函数内部都是不可见的。

但请注意,Octave 不允许在脚本 M 文件末尾添加本地函数,因此使用时不会定义

click
。在 MATLAB 中它可以工作,但在 Octave 中不行。在 Octave 中,您必须在使用函数声明之前将其移动到脚本中的某个位置。

在这种形式中,您必须将句柄作为参数传递给函数。例如,您可以定义

function click(handle,src)

然后,您作为回调传递的句柄将是

@click
,而不是
@(src,~)click(handle,src)

© www.soinside.com 2019 - 2024. All rights reserved.