3

状況

特定の時間に位置の座標があるとします。データが次のようになるとしましょう

data = A[rand(100, 3), sort(rand(100, 1))]

ここでdata(:,1)、はx座標、data(:,2)y座標、data(:,3)高さ、およびdata(:,4)記録時間です。

を使用してそのデータを簡単にプロットできます

pxy = subplot(2,2,1)            % Plot for X-Y-Data
plot(data(:,1), data(:,2))
ptx = subplot(2,2,2)            % Plot for T-X-Data
plot(data(:,4), data(:,1))
pty = subplot(2,2,3)            % ... and so on
plot(data(:,4), data(:,2))
pth = subplot(2,2,4)
plot(data(:,4), data(:,3))

さて、図を見るために、軸を同期させるのは素晴らしいことです。

可能性についての最初の考え

linkaxes些細なアプローチは、次のような時間軸に使用できます。

linkaxes([ptx, pty, pth], 'x')

ただし、これによりxyプロットは変更されません。したがって、より弱い質問は、のy軸ptxをのx軸にリンクする方法ですpxy

しかし、さらに複雑にしましょう。

実際の質問

プロットが2つしかないpxyとしpthます。pxyこれで、で表示されているタイムスパンでズームまたはパンするたびに、それに応じpxyて抽出およびpth変更されると便利です。同様に、ズームは、正しい期間のデータのみが表示されるようにpth変更されます。pxy

このアプローチは、4つの可能なプロットの任意のサブセットをプロットできるようにスケーラブルである必要があり、それに応じてリンクが実行されます。

これを達成する方法はありますか?

最適なソリューションでは、を使用してさらにデータを追加することにより、そのベースプロットを変更できますhold on

4

2 に答える 2

2

必要なものに関する(理論上の)問題は、pxyが反転可能である必要があることであり、離散領域(matlabは離散)では、これはさらに不明確になります。

pxyで互いに近い2つの点P1=(x1、y1)とP2 =(x2、y2)があるとします。P1とP2の両方がpxyで表示されている場合、pthのどのaxes-windowにpxyのaxes-windowを対応させますか?Pth1またはPth2?このためのいくつかの決定ルールを定義する必要があります。おそらく、実際にクリックした2つ(P1またはP2)のどちらに基づいていますか。

実際には、ユーザーがpxyのズームを変更したときに軸を変更する関数を実行する必要があります。これは、http://www.mathworks.com/matlabcentral/answers/21627-triggering-changes-in-plotで説明されているように実行できます。 -with-zoom-function

于 2012-05-04T10:21:26.023 に答える
1

Gunthersのヒントの結果、私は自分で問題を解決することができました。Gunthersの回答にはまだかなりの調査が必要なので、誰かが同様の問題に遭遇した場合に備えて、以下に独自の解決策を示します。

まず、axis-objectにUserDataとして必要なデータのほとんどを追加しました。私のプロット関数(2つのプロットのみ)はおおよそ次のようになります。

sb1 = subplot(1, 2, 1);
plot(data(:,1), data(:,2));
axis equal;
sb2 = subplot(1, 2, 2);
plot(data(:,4), data(:,3));
set(sb1, 'UserData', struct('projection', 'xy', 'data', data, 'link', [sb2]));
set(sb2, 'UserData', struct('projection', 'th', 'data', data, 'link', [sb1]));
panzoom(sb1, 'setlimits');   % Those two lines ensure that the zoom limits won't get changed
panzoom(sb2, 'setlimits');   % over time.

次に、ハンドラーをズーム機能に設定します。

z = zoom;
set(z, 'ActionPostCallback', @Track.synchronizePlots);
z = pan;
set(z, 'ActionPostCallback', @Track.synchronizePlots);

そして最後に、これは魔法が起こる場所です:

function synchronizePlots(obj, ax)
    ax = ax.Axes;           
    ud = get(ax, 'UserData');

    if ud.projection == 'xy'
        % That is the part discussed in the comments above,
        % which is, as I freely admit, not very sensible on a strict
        % mathematical point of view. However, the result is good enough for my
        % purpose
        xrange = get(ax, 'XLim');
        yrange = get(ax, 'YLim');
        pointsvisible = ud.data(1,:) >= xrange(1) & ...
                        ud.data(1,:) <= xrange(2) & ...
                        ud.data(2,:) >= yrange(1) & ...
                        ud.data(2,:) <= yrange(2);
        r = [min(ud.data(4, pointsvisible)), max(ud.data(4, pointsvisible))];
        if length(r) == 0  % The trick above may fail if there is no point in the zoom region.
            return         % in that case we just do nothing.
        end
    else
        r = get(ax, 'XLim');  % Straightforward
    end


    for a = ud.link  % The function does not care about the number of figures that have to be changed.
        linkud = get(a, 'UserData');

        if linkud.projection == 'xy'
            % Again, changing the xy-plot is that only part we have to work.
            pointsintime = linkud.data(4,:) >= r(1) & ...
                           linkud.data(4,:) <= r(2);
            xrange = [min(linkud.data(1, pointsintime)), ...
                      max(linkud.data(1, pointsintime))];
            yrange = [min(linkud.data(2, pointsintime)), ...
                      max(linkud.data(2, pointsintime))];
            if length(xrange) > 0
                 set(a, 'XLim', xrange);
                 set(a, 'YLim', yrange);
                 axis(a, 'equal');
            end
        else
            set(a, 'XLim', r);
        end
    end

それが誰かを助けることを願っています。

于 2012-05-04T16:45:54.717 に答える