チャート クラスのプロパティの管理
ChartContainer
基底クラスのサブクラスとしてカスタム チャートを作成する際には、特定の手法を使ってコードをよりロバストに、効率的に、またユーザーのニーズに沿ったものにできます。これらの手法では、ユーザー クラスのプロパティを定義し管理する方法に焦点を当てます。作成される可視化のタイプと提供されるユーザー エクスペリエンスに役立つものは、すべて使用します。
プロパティ値の初期化 — ユーザーが入力引数なしで暗黙的なコンストラクターを呼び出す場合に備えて、チャートの既定の状態を設定します。
プロパティ値の検証 — 値を使って計算を実行したり、チャート内の基となるグラフィックス オブジェクトの 1 つを構成する前に、その値が有効であることを確認します。
プロパティ表示のカスタマイズ — ユーザーがセミコロンなしでチャート オブジェクトを参照すると、プロパティのカスタマイズされたリストを提示します。
update
メソッドの最適化 — 時間のかかる計算にプロパティのサブセットのみが使用されている場合、update
メソッドのパフォーマンスを改善します。
プロパティ値の初期化
ユーザー クラスのパブリック プロパティすべてに対し既定値を割り当てます。そうすることで、ユーザーがコンストラクター メソッドを呼び出す際に名前と値のペアの引数をいくつか省略しても、有効なチャートが構成されます。
座標のデータを保存するプロパティでは、初期値を NaN
値または空の配列に設定し、ユーザーが座標を指定しない場合は既定のチャートが空になるようにします。ユーザー クラスのメソッドで呼び出す予定のプロット関数の要件に従って、既定の座標を選択します。要件の詳細については、使用予定のプロット関数のドキュメンテーションを参照してください。
プロパティ値の検証
ユーザー クラス プロパティの値をコードで使用する前に、それらの値を検証することをお勧めします。これを行う便利な方法は、プロパティを定義する際にそのサイズとクラスを検証することです。たとえば、次のプロパティ ブロックでは、4 つのプロパティのサイズとクラスが検証されます。
properties IsoValue (1,1) double = 0.5 Enclose {mustBeMember(Enclose,{'above','below'})} = 'below' CapVisible (1,1) matlab.lang.OnOffSwitchState = 'on' Color (1,3) double {mustBeGreaterThanOrEqual(Color,0),... mustBeLessThanOrEqual(Color,1)} = [.2 .5 .8] end
IsoValue
はクラスdouble
の 1 行 1 列の配列でなければならない。Enclose
は'above'
または'below'
の値をもたなければならない。CapVisible
はクラスmatlab.lang.OnOffSwitchState
の 1 行 1 列の配列でなければならない。Color
は、それぞれの値が範囲[0,1]
内にある、クラスdouble
の 1 行 3 列の配列でなければならない。
チャートにおいて、基となるグラフィックス オブジェクトを保存するプロパティを検証することもできます。オブジェクトのクラス名を判定するには、コマンド ラインで対応するプロット関数を呼び出し、続いて関数 class
を呼び出してクラス名を取得します。たとえば、setup
メソッドで関数 patch
を呼び出す予定の場合は、コマンド ラインで出力引数を指定して関数 patch
を呼び出します (入力引数は重要でない)。次に、出力を関数 class
に渡してそのクラス名を取得します。
x = patch(NaN,NaN,NaN); class(x)
ans = 'matlab.graphics.primitive.Patch'
関数 class
の出力を使用して、ユーザー クラスで対応するプロパティについてクラスを検証します。たとえば、次のそれぞれのプロパティには Patch
オブジェクトが格納されています。
properties (Access = private,Transient,NonCopyable) IsoPatch (1,1) matlab.graphics.primitive.Patch CapPatch (1,1) matlab.graphics.primitive.Patch end
場合によっては、異なった形状とクラスの値を格納できるプロパティを定義することもできます。たとえば、文字ベクトル、文字ベクトルの cell 配列、または string 配列を格納できるプロパティを定義する場合は、サイズとクラスの検証を省略するか、カスタムのプロパティ検証法を使用します。
プロパティ検証の詳細については、プロパティ値の検証を参照してください。
プロパティ表示のカスタマイズ
チャートを ChartContainer
基底クラスのサブクラスとして定義する利点の 1 つは、matlab.mixin.CustomDisplay
クラスからの継承もあることです。したがって、チャートをセミコロンなしで参照したときに MATLAB® がコマンド ウィンドウに表示するプロパティのリストをカスタマイズすることができます。プロパティ表示をカスタマイズするには、getPropertyGroups
メソッドをオーバーロードします。そのメソッド内で、リストされるプロパティとリストの順序をカスタマイズできます。たとえば、次のパブリック プロパティをもつ IsoSurfCapChart
クラスについて考えます。
properties IsoValue (1,1) double = 0.5 Enclose {mustBeMember(Enclose,{'above','below'})} = 'below' CapVisible (1,1) matlab.lang.OnOffSwitchState = 'on' Color (1,3) double {mustBeGreaterThanOrEqual(Color,0),... mustBeLessThanOrEqual(Color,1)} = [.2 .5 .8] end
次の getPropertyGroups
メソッドは、スカラー オブジェクトのプロパティ リストを Color
、IsoValue
、Enclose
、および CapVisible
として指定します。
function propgrp = getPropertyGroups(obj) if ~isscalar(obj) % List for array of objects propgrp = getPropertyGroups@matlab.mixin.CustomDisplay(obj); else % List for scalar object propList = {'Color','IsoValue','Enclose','CapVisible'}; propgrp = matlab.mixin.util.PropertyGroup(propList); end end
ユーザーがこのチャートのインスタンスをセミコロンなしで参照すると、MATLAB はカスタマイズされたリストを表示します。
c = IsoSurfCapChart
c = IsoSurfCapChart with properties: Color: [0.2000 0.5000 0.8000] IsoValue: 0.5000 Enclose: 'below' CapVisible: on
プロパティ表示のカスタマイズの詳細については、プロパティ表示のカスタマイズを参照してください。
update
メソッドの最適化
ほとんどの場合、ユーザー クラスの update
メソッドは、パブリック プロパティに依存するチャートのあらゆる関連特性を再構成します。場合によっては、再構成には時間のかかる高負荷な計算が伴います。計算にプロパティのサブセットのみが関与する場合は、そのコードが必要な場合にのみ実行されるようにユーザー クラスを設計できます。
update
メソッドを最適化する 1 つの方法は、以下のコンポーネントをユーザー クラスに追加することです。
logical
値を受け入れるExpensivePropChanged
というプライベート プロパティを定義する。このプロパティは、高負荷な計算に使用されるプロパティのいずれかが変更されたかどうかを示します。高負荷な計算に関与する各プロパティ用に
set
メソッドを作成する。各set
メソッド内で、ExpensivePropChanged
プロパティをtrue
に設定します。高負荷な計算を実行する保護されたメソッドを作成する。
update
メソッド内に、ExpensivePropChanged
の値をチェックする条件付きステートメントを作成する。値がtrue
である場合は、高負荷な計算を行うメソッドを実行します。
以下のコードは、この設計の簡易実装を示しています。
classdef OptimizedChart < matlab.graphics.chartcontainer.ChartContainer properties Prop1 Prop2 end properties(Access=private,Transient,NonCopyable) ExpensivePropChanged (1,1) logical = true end methods(Access = protected) function setup(obj) % Configure chart % ... end function update( obj ) % Perform expensive computation if needed if obj.ExpensivePropChanged doExpensiveCalculation(obj); obj.ExpensivePropChanged = false; end % Update other aspects of chart % ... end function doExpensiveCalculation(obj) % Expensive code % ... end end methods function set.Prop2(obj,val) obj.Prop2 = val; obj.ExpensivePropChanged = true; end end end
Prop2
が高負荷な計算に関与しています。set.Prop2
メソッドは Prop2
の値を設定し、続いて ExpensivePropChanged
を true
に設定します。したがって、次に update
メソッドが実行されるときは、ExpensivePropChanged
が true
である場合にのみ doExpensiveCalculation
が呼び出されます。その後、update
メソッドはチャートの他の特性を引き続き更新します。例: カスタマイズされたプロパティ表示をもつ最適化された等値面チャート
isocaps
の関連付けられた isosurface
を表示するために IsoSurfCapChart
クラスを定義します。以下の機能を含めます。
サイズとクラスの検証を使用するプロパティ
カスタマイズされたプロパティ表示
1 つ以上の関連プロパティが変更された場合にのみ
isosurface
およびisocaps
を再計算する、最適化されたupdate
メソッド
このクラスを定義するために、MATLAB パス上にあるフォルダー内に IsoSurfCapChart.m
というプログラム ファイルを作成します。次に、表にある手順に従ってクラスを実装します。
手順 | 実装 |
---|---|
|
classdef IsoSurfCapChart < matlab.graphics.chartcontainer.ChartContainer |
クラスとサイズの検証を使用するパブリック プロパティを定義します。
| properties VolumeData double = rand(25,25,25) IsoValue (1,1) double = 0.5 Enclose {mustBeMember(Enclose,{'above','below'})} = 'below' WhichCapPlane {mustBeMember(WhichCapPlane,{'all','xmin',... 'xmax','ymin','ymax','zmin','zmax'})} = 'all' CapVisible (1,1) matlab.lang.OnOffSwitchState = 'on' Color (1,3) double {mustBeGreaterThanOrEqual(Color,0),... mustBeLessThanOrEqual(Color,1)} = [.2 .5 .8] end |
プライベート プロパティを定義します。
|
properties(Access = private,Transient,NonCopyable) IsoPatch (1,1) matlab.graphics.primitive.Patch CapPatch (1,1) matlab.graphics.primitive.Patch SmoothData double = []; ExpensivePropChanged (1,1) logical = true end |
|
methods(Access = protected) function setup(obj) ax = getAxes(obj); % Create two Patch objects obj.IsoPatch = patch(ax,NaN,NaN,NaN, 'EdgeColor', 'none', ... 'FaceColor',[.2 .5 .8],'FaceAlpha',0.9); hold(ax,'on'); obj.CapPatch = patch(ax,NaN,NaN,NaN,'EdgeColor', 'none', ... 'FaceColor','interp'); % Configure the axes view(ax,3) camlight(ax, 'infinite'); camlight(ax,'left'); lighting(ax, 'gouraud'); hold(ax,'off'); end |
|
function update(obj) % Perform expensive computation if needed if obj.ExpensivePropChanged doExpensiveCalculation(obj); obj.ExpensivePropChanged = false; end % Update visibility of CapPatch and update color obj.CapPatch.Visible = obj.CapVisible; obj.IsoPatch.FaceColor = obj.Color; end |
|
function doExpensiveCalculation(obj) % Update isosurface obj.SmoothData = smooth3(obj.VolumeData,'box',7); [F,V] = isosurface(obj.SmoothData, obj.IsoValue); set(obj.IsoPatch,'Faces',F,'Vertices',V); isonormals(obj.SmoothData,obj.IsoPatch); % Update isocaps [m,n,p] = size(obj.SmoothData); [Xc,Yc,Zc] = meshgrid(1:n,1:m,1:p); [Fc,Vc,Cc] = isocaps(Xc,Yc,Zc,obj.SmoothData,obj.IsoValue,... obj.Enclose,obj.WhichCapPlane); set(obj.CapPatch,'Faces',Fc,'Vertices',Vc,'CData',Cc); end |
|
function propgrp = getPropertyGroups(obj) if ~isscalar(obj) % List for array of objects propgrp = getPropertyGroups@matlab.mixin.CustomDisplay(obj); else % List for scalar object propList = {'Color','IsoValue','Enclose','CapVisible',... 'WhichCapPlane','VolumeData'}; propgrp = matlab.mixin.util.PropertyGroup(propList); end end end |
計算量の多い各プロパティ ( |
methods function set.VolumeData(obj,val) obj.VolumeData = val; obj.ExpensivePropChanged = true; end function set.IsoValue(obj, val) obj.IsoValue = val; obj.ExpensivePropChanged = true; end function set.Enclose(obj, val) obj.Enclose = val; obj.ExpensivePropChanged = true; end end end |
次に、ボリューム データの配列を作成し、続いて IsoSurfCapChart
のインスタンスを作成します。
[X,Y,Z] = meshgrid(-2:0.1:2); v = (1/9)*X.^2 + (1/16)*Y.^2 + Z.^2; c = IsoSurfCapChart('VolumeData',v,'IsoValue',0.5)
c = IsoSurfCapChart with properties: Color: [0.2000 0.5000 0.8000] IsoValue: 0.5000 Enclose: 'below' CapVisible: on WhichCapPlane: 'all' VolumeData: [41×41×41 double]
c
の色を変更し、isocaps
を非表示にします。
c.Color = [1 0.60 0]; c.CapVisible = false;