Main Content

グラフィックス プロパティを取得および設定するコードの最適化

自動計算されるプロパティ

他のプロパティの値との依存関係をもつプロパティがあります。MATLAB® では、自動的にこのようなプロパティの値が計算され、現在のグラフィックス モデルに基づいて値が更新されます。たとえば、軸の範囲により、軸の目盛りに使用される値が変わります。さらに、この値により、軸の目盛りラベルが変わります。

計算されたプロパティをクエリすると、MATLAB では drawnow が暗黙的に実行され、すべてのプロパティ値を最新状態にしてから、計算されたプロパティ値を返します。このクエリにより、依存するすべてのプロパティの完全更新と、画面の更新が行われます。

MATLAB では、一部のプロパティの値が、そのプロパティが依存している他の値に基づいて計算されます。たとえば、プロット関数は、プロットされるデータと Figure のサイズに適した軸の範囲、目盛りラベル、サイズを使用して、座標軸を自動的に作成します。

MATLAB グラフィックスは、計算されたプロパティの値を返す前に、その値が確実に最新状態となるよう、必要に応じてすべての更新を行います。

次の表に、よく計算されるプロパティの一部を示します。

オブジェクトプロパティこれらのプロパティの MATLAB による計算

axes

CameraPosition, CameraTarget, CameraUpVector, CameraViewAngle

常時

 

Position, OuterPosition, TightInset

常時

 

XLim, YLim, ZLim

常時

 

XTick, YTick, ZTick, XMinorTick, YMinorTick, ZMinorTick

常時

 

XTickLabel, YTickLabel, ZTickLabel, TickDir

常時

 

SortMethod

常時

text

Extent

常時

 

Position

text オブジェクトが座標軸のタイトルまたは軸ラベルとして使用されている場合のみ

 

FontSize, FontWeight

text オブジェクトが座標軸のタイトルまたは軸ラベルとして使用されている場合のみ

set と get の非効率なサイクル

プロパティ値を設定するときには、グラフィックス モデルの状態を変更し、要更新としてマークします。自動計算されたプロパティをクエリする場合、グラフィックス モデルとグラフィックス ハードウェアが同期していないときには、MATLAB による更新の実行が必要です。

同じループ内でプロパティを取得および設定する場合、1 回ループするたびに更新を実行していることがあります。

  • get は更新を引き起こします。

  • set はグラフィックス モデルを要更新としてマークします。

1 回ループするたびにこのサイクルが繰り返されます。このようにするよりも、以下の例に示すように、1 回のループですべてのプロパティのクエリを実行してから、別のループですべてのプロパティの設定を行った方が効率的です。

この例では、テキストの Extent プロパティを取得および設定しています。

パフォーマンスが悪いコードパフォーマンスが良いコード
h = gobjects(1,500);
p = zeros(500,3);
for ix = 1:500
   h(ix) = text(ix/500,ix/500,num2str(ix));
end
drawnow

% Gets and sets in the same loop,
% prompting a full update at each pass
for ix = 1:500
   pos = get(h(ix),'Position');
   ext = get(h(ix),'Extent');
   p(ix,:) = [pos(1)+(ext(3)+ext(1)), ...
              pos(2)+ext(2)+ext(4),0];
   set(h(ix),'Position',p(ix,:))
end
drawnow
h = gobjects(1,500);
p = zeros(500,3);
for ix = 1:500
   h(ix) = text(ix/500,ix/500,num2str(ix));
end
drawnow

% Get and save property values
for ix=1:500
   pos = get(h(ix),'Position');
   ext = get(h(ix),'Extent');
   p(ix,:) = [pos(1)+(ext(3)+ext(1)), ...
              pos(2)+ext(2)+ext(4),0];
end

% Set the property values and 
% call a drawnow after the loop
for ix=1:500
   set(h(ix),'Position',p(ix,:));
end
drawnow

このコードのパフォーマンスが悪い理由は、以下のとおりです。

  • Extent プロパティは画面の解像度、Figure のサイズ、軸の範囲など他の値に依存しているため、このプロパティをクエリすると、すべての更新が起こる可能性がある。

  • Position プロパティを設定するごとに、次回の Extent プロパティの取得ですべての更新が必要となる。

このコードのパフォーマンスが良い理由は、以下のとおりです。

  • 1 つのループですべてのプロパティ値をクエリし、それらの値を配列に格納している。

  • 別のループですべてのプロパティ値を設定している。

  • 2 番目のループが終了した後で drawnow を呼び出している。

テキストの Extent の変更によるラベルの回転

座標軸のラベルが回転するようテキストの Extent プロパティを変更する場合には、座標軸のプロパティ XTickLabelRotationYTickLabelRotationZTickLabelRotation を使用すると、より効率的です。