Управление свойствами классов графика

Когда вы разрабатываете пользовательский график как подкласс ChartContainer базовый класс, вы можете использовать определенные методы, чтобы сделать ваш код более надежным, эффективным, и адаптированным к потребностям ваших пользователей. Эти методы фокусируются на том, как вы определяете и управляете свойствами своего класса. Используйте все, что полезно для типа визуализации, которую вы хотите создать, и пользовательского опыта, который вы хотите предоставить.

  • Инициализируйте значения свойств - Установите состояние графика по умолчанию в случае, если ваши пользователи вызывают неявный конструктор без каких-либо входных параметров.

  • Проверьте значения свойств - Убедитесь, что значения действительны, прежде чем использовать их, чтобы выполнить вычисление или сконфигурировать один из базовых графических объектов на графике.

  • Настройка отображения свойств - Обеспечивайте настраиваемый список свойств, когда пользователь ссылается на объект графика без точки с запятой.

  • Оптимизируйте update метод - Улучшение эффективности update метод, когда в длительном вычислении используется только подмножество ваших свойств.

Инициализация значений свойств

Назначьте значения по умолчанию для всех общественной собственности вашего класса. Это настраивает допустимый график, если пользователь опускает некоторые аргументы пары "имя-значение" при вызове метода конструктора.

Для свойств, которые хранят данные координат, установите начальные значения NaN значения или пустые массивы, так что график по умолчанию пуст, когда пользователь не задает координаты. Выберите координаты по умолчанию в соответствии с требованиями функций построения графика, которую вы планируете вызвать, в своих методах классом. Для получения информации о требованиях см. документацию по функциям построения графика, которые вы планируете использовать.

Валидация значений свойств

Хорошей практикой является проверка значений свойств класса до того, как код использует эти значения. Удобный способ сделать это - проверить размер и класс свойств по мере их определения. Для примера этот блок свойств проверяет размер и класс четырех свойств.

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 должен быть массивом класса 1 на 1 double.

  • Enclose должно иметь значение любой из 'above' или 'below'.

  • CapVisible должен быть массивом класса 1 на 1 matlab.lang.OnOffSwitchState.

  • Color должен быть массивом класса 1 на 3 double, где каждое значение находится в области значений [0,1].

Можно также проверить свойства, которые хранят базовые графические объекты на графике. Чтобы определить имя класса объекта, вызовите соответствующую функцию построения графика в командной строке, а затем вызовите class функция для получения имени класса. Для примера, если вы планируете вызвать patch функция в вашем setup method, вызывать 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

Иногда можно хотеть задать свойство, которое может хранить различные формы и классы значений. Для примера, если вы задаете свойство, которое может хранить вектор символов, массив ячеек векторов символов или строковых массивов, опускайте размер и валидацию класса или используйте пользовательский метод валидации свойств.

Дополнительные сведения о проверке свойств см. в разделе Проверка значений свойств.

Настройка отображения свойств

Одно из преимуществ определения вашего графика как подкласса ChartContainer базовый класс - это то, что он также наследует от 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 метод состоит в том, чтобы добавить эти компоненты к вашему классу:

  • Задайте частную собственность под названием ExpensivePropChanged который принимает logical значение. Это свойство указывает, изменились ли какие-либо свойства, используемые в дорогостоящем вычислении.

  • Написание 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 участвует в дорогостоящем расчете. The set.Prop2 метод устанавливает значение Prop2и затем устанавливает ExpensivePropChanged на true. Таким образом, в следующий раз update метод запускается, он вызывает doExpensiveCalculation только если ExpensivePropChanged является true. Затем update метод продолжает обновлять другие аспекты графика.

Пример: Оптимизированная Изоповерхность Графика с настроенным отображением свойств

Задайте IsoSurfCapChart класс для отображения isosurface со связанными isocaps. Включите следующие функции:

  • Свойства, которые используют валидацию размера и класса

  • Отображение настроенного свойства

  • Оптимизированное update метод, который пересчитывает isosurface и isocaps только в случае изменения одного или нескольких соответствующих свойств

Чтобы определить этот класс, создайте программный файл с именем IsoSurfCapChart.m в папке, расположенной в пути MATLAB. Затем реализуйте класс путем следования шагам в таблице.

ШагРеализация

Вывод из ChartContainer базовый класс.

classdef IsoSurfCapChart < matlab.graphics.chartcontainer.ChartContainer

Определите общественную собственность с помощью валидации класса и размера.

  • VolumeData, IsoValue, и Color являются параметрами для isosurface.

  • Enclose, WhichCapPlane, и CapVisible являются параметрами для isocaps.

    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

Задайте частную собственность.

  • IsoPatch и CapPatch хранить Patch объекты для isosurface и isocaps.

  • SmoothData сохраняет сглаженную версию данных тома.

  • ExpensivePropChanged указывает, нужно ли методу обновления пересчитывать isosurface и isocaps.

    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

Реализуйте setup способ. В этом случае вызовите patch дважды функция для создания Patch объекты для isosurface и isocaps. Сохраните объекты в соответствующих свойствах и сконфигурируйте оси.

    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

Реализуйте update способ. Решите, вызывать ли doExpensiveCalculation метод путем проверки значения ExpensivePropChanged. Затем продолжите обновление других (менее дорогих) аспектов графика.

        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

Реализуйте doExpensiveCalculation метод, который сглаживает объемные данные и пересчитывает грани и вершины isosurface и isocaps.

        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

Реализуйте getPropertyGroups метод для настройки отображения свойств.

        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

Реализуйте set методы для каждого дорогого свойства (VolumeData, IsoValue, и Enclose). В рамках каждого метода задайте соответствующее значение свойства и затем установите ExpensivePropChanged на true.

    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;

См. также

Классы

Функции

Похожие темы