www.gusucode.com > mbcdesign 工具箱 matlab 源码程序 > mbcdesign/+xregdesgui/ConView3d.m

    classdef ConView3d < xregdesgui.DesignView
    %xregdesgui.ConView3d class
    %   xregdesgui.ConView3d extends xregdesgui.DesignView.
    %
    %    xregdesgui.ConView3d properties:
    %       Parent - Property is of type 'MATLAB array'
    %       Position - Property is of type 'rect'
    %       Enable - Property is of type 'on/off'
    %       Visible - Property is of type 'on/off'
    %       Userdata - Property is of type 'MATLAB array'
    %       Tag - Property is of type 'string'
    %       Display - Property is of type 'MATLAB array' (read only)
    %       MessageService - Property is of type 'handle'
    %       Options - Property is of type 'handle vector'
    %       Actions - Property is of type 'handle vector'
    %       UIContextMenu - Property is of type 'MATLAB array'
    %       Resolution - Property is of type 'double'
    %       Xaxis - Property is of type 'double'
    %       Yaxis - Property is of type 'double'
    %       Zaxis - Property is of type 'double'
    %       EvalPoint - Property is of type 'MATLAB array'
    %
    %    xregdesgui.ConView3d methods:
    %       gettitle - Return a suitable title for a window
    %       printCopy - Create a new component for printing the component display
    
    %  Copyright 2015 The MathWorks, Inc. and Ford Global Technologies, Inc.

    properties (AbortSet, SetObservable)
        %RESOLUTION Property is of type 'double'
        Resolution = 30;
    end
    properties (Dependent,AbortSet)
        %XAXIS Property is of type 'double'
        Xaxis
        %YAXIS Property is of type 'double'
        Yaxis
        %ZAXIS Property is of type 'double'
        Zaxis        
        %EVALPOINT Property is of type 'MATLAB array'
        EvalPoint = [];
    end    
    
    properties (Access=protected, AbortSet)
        %HAXES Property is of type 'MATLAB array'
        hAxes = [];
        %HPATCH Property is of type 'MATLAB array'
        hPatch = [];
        %NODISPLAYTEXT Property is of type 'MATLAB array'
        nodisplaytext = [];
        %HRESOLUTION Property is of type 'handle'
        hResolution = [];
        %HSLICECONTROL Property is of type 'handle'
        hSliceControl = [];
    end
    
    
    methods  % constructor block
        function obj = ConView3d(varargin)
        %CONVIEW3D Constructor for conview3d objects
        %  CONVIEW3D(PROP, VALUE, ...) constructs a new conview2d object.
        
        obj@xregdesgui.DesignView(varargin{ : }); % converted super class constructor call
        
        
        % Generate GUI primitives and link together into a layout
        axlyt = mbcgui.widget.AxesContainer(...
            'Parent',obj.Parent, ...
            'PositionSetting','outer',...
            'Border', [10 10 10 10]);
        obj.hAxes = axlyt.AxesHandle;
        set(obj.hAxes, ...
            'UIContextMenu',obj.UIContextMenu,...
            'Box','on',...
            'XGrid','on',...
            'YGrid','on',...
            'Units','pixels',...
            'Layer','top');
        
        view(obj.hAxes, 3);
        mbcgraph.camlight(obj.hAxes, 'headlight');
        mv_rotate3d(obj.hAxes, 'ON');
        
        mbcxlabel(obj.hAxes, '', 'Interpreter', 'none');
        mbcylabel(obj.hAxes, '', 'Interpreter', 'none');
        mbczlabel(obj.hAxes, '', 'Interpreter', 'none');
        obj.hPatch = patch('Parent',obj.hAxes, ...
            'EdgeColor', 'none', ...
            'FaceColor', [0.5 0.5 1], ...
            'FaceLighting', 'gouraud', ...
            'BackFaceLighting', 'unlit', ...
            'AmbientStrength', .3, ...
            'DiffuseStrength', .6, ...
            'SpecularStrength', .9, ...
            'SpecularExponent', 10, ...
            'SpecularColorReflectance', .8, ...
            'LineStyle', 'none', ...
            'XData', NaN, ...
            'YData', NaN, ...
            'HitTest', 'off');
        xregGui.setLegendData(obj.hPatch, 'Constrained region');
        obj.nodisplaytext = text('Parent',obj.hAxes,...
            'String','',...
            'Position',[.5 .5 .5],...
            'HorizontalAlignment','center',...
            'VerticalAlignment','middle',...
            'Clipping','on',...
            'HitTest','off');
        
        hPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'Visible', obj.Visible, ...
            'BorderType', 'beveledout', ...
            'LayoutBorder', [5 5 5 5]);
        resedit = mbcgui.widget.Spinner('Parent',hPanel,...
            'Rule','int',...
            'Min',1,...
            'Max',100,...
            'Value', obj.Resolution, ...
            'ClickIncrement',1,...
            'Callback', @iSetResolutionFromSpinner);
        obj.hResolution = xregGui.labelcontrol('parent', hPanel, ...
            'String', 'Resolution:', ...
            'LabelAlignment', 'right', ...
            'ControlSize', 60, ...
            'Control', resedit);
        set(hPanel, 'LayoutComponent', obj.hResolution);
        
        obj.hSliceControl = xregdesgui.SliceControl('NumAxes', 3, ...
            'Parent', obj.Parent);
        obj.ContentHandle = xreggridbaglayout(obj.Parent,...
            'packgroup','XREGCONVIEWERS',...
            'dimension',[2 3],...
            'rowsizes',[-1 32],...
            'colsizes',[160 150 -1],...
            'mergeblock',{[1 2],[2 3]},...
            'elements',{obj.hSliceControl, hPanel, axlyt},...
            'position',obj.Position, ...
            'packstatus','on');
        
        obj.pPostSetMessageService;
        
        % Attach listeners to properties and slice control events
        obj.addListeners( ...
            [event.listener(obj.hSliceControl, 'AxisChanged', @iRedrawgraph), ...
            event.listener(obj.hSliceControl, 'PointChanged', @iRedrawgraph)] ...
            );
        
            function iSetResolutionFromSpinner(src, ~)
            obj.Resolution = src.Value;
            end
        
            function iRedrawgraph(~, ~)
            PR = xregGui.PointerRepository;
            ptrID = PR.stackSetPointer(obj.Parent, 'watch');
            obj.pDrawGraph;
            PR.stackRemovePointer(obj.Parent, ptrID);
            end
        end
        
        
    end  % constructor block
    
    methods
        function set.Resolution(obj,value)
        % DataType = 'double'
        validateattributes(value,{'double'}, {'scalar'},'','Resolution')
        obj.Resolution = value;
        
        busy(obj.MessageService)
        obj.pDrawGraph;
        idle(obj.MessageService);
        end
        
        function fact = get.Xaxis(obj)
        if ~isempty(obj.hSliceControl)
            fact = obj.hSliceControl.Axes(1);
        else
            fact = 0;
        end

        end
        function set.Xaxis(obj,fact)
        % DataType = 'double'
        
        if ~isempty(obj.hSliceControl)
            obj.hSliceControl.Axes(1) = fact;
            obj.pDrawGraph;
        end        
        
        end
        
        function fact = get.Yaxis(obj)
        
        if ~isempty(obj.hSliceControl)
            fact = obj.hSliceControl.Axes(2);
        else
            fact = 0;
        end

        end
        function set.Yaxis(obj,fact)
        % DataType = 'double'
        if ~isempty(obj.hSliceControl)
            obj.hSliceControl.Axes(2) = fact;
            obj.pDrawGraph;
        end        
        end
        
        function fact = get.Zaxis(obj)
        
        if ~isempty(obj.hSliceControl)
            fact = obj.hSliceControl.Axes(3);
        else
            fact = 0;
        end

        end
        
        function set.Zaxis(obj,fact)
        % DataType = 'double'
        if ~isempty(obj.hSliceControl)
            obj.hSliceControl.Axes(3) = fact;
            obj.pDrawGraph;
        end        
        end        
        
        function pt = get.EvalPoint(obj)
        if ~isempty(obj.hSliceControl)
            pt = obj.hSliceControl.SlicePoint;
        else
            pt = [];
        end
        end
        function set.EvalPoint(obj,pt)
        if ~isempty(obj.hSliceControl)
            obj.hSliceControl.SlicePoint = pt;
            obj.pDrawGraph;
        end        
        end
        
        function set.hResolution(obj,value)
        % DataType = 'handle'
        validateattributes(value,{'handle'}, {'scalar'},'','hResolution')
        obj.hResolution = value;
        end
        
        function set.hSliceControl(obj,value)
        % DataType = 'handle'
        validateattributes(value,{'handle'}, {'scalar'},'','hSliceControl')
        obj.hSliceControl = value;
        end
        
    end   % set and get functions
    
    methods  % public methods
        %----------------------------------------
        function s = gettitle(obj) %#ok<MANU>
        %GETTITLE Return a suitable title for a window
        %  GETTITLE(OBJ) returns a string that can be sued as a title for the view.
        
        s = '3D Constraints';
        
        end  % gettitle
        
        %----------------------------------------
        function pDrawGraph(obj)
        %PDRAWGRAPH Draw constraint region on graph
        %  PDRAWGRAPH(obj) updates the constraint graph.
        
        if obj.hSliceControl.hasSlice
            d = obj.MessageService.getdesign;
            sc = obj.hSliceControl;
            
            Xax = sc.Axes(1);
            Yax = sc.Axes(2);
            Zax = sc.Axes(3);
            
            % set axes labels
            fstr = factors(d);
            mbcxlabel(obj.hAxes, fstr{Xax});
            mbcylabel(obj.hAxes, fstr{Yax});
            mbczlabel(obj.hAxes, fstr{Zax});
            
            
            % generate points and constrain them
            m = model(d);
            lims = designlimits(d);
            codedlims = cat(1,lims{:});
            lims = invcode(m,codedlims')';
            
            % generate and constrain points
            c = constraints(d);
            
            if isempty(c);
                F=[1 2 4 3
                    1 2 6 5
                    1 5 7 3
                    3 4 8 7
                    2 6 8 4
                    5 6 8 7
                    ];
                V=[lims(Xax,1) lims(Yax,1) lims(Zax,1);...
                    lims(Xax,1) lims(Yax,1) lims(Zax,2);...
                    lims(Xax,1) lims(Yax,2) lims(Zax,1);...
                    lims(Xax,1) lims(Yax,2) lims(Zax,2);...
                    lims(Xax,2) lims(Yax,1) lims(Zax,1);...
                    lims(Xax,2) lims(Yax,1) lims(Zax,2);...
                    lims(Xax,2) lims(Yax,2) lims(Zax,1);...
                    lims(Xax,2) lims(Yax,2) lims(Zax,2);...
                    ];
                set( obj.hPatch,'VertexNormalsMode','auto');
                set(obj.hPatch,...
                    'Vertices',V, ...
                    'Faces',F);
            else
                res = max(3,floor(obj.Resolution));
                pt = sc.SlicePoint; %>> code(m, sc.SlicePoint);
                ISOvalue = .5;
                K = ones([3 3 3]);
                K([1 3],[1 3],[1 3]) = .6;
                K(2,[1 3],[1 3]) = .7;
                K([1 3],2,[1 3]) = .7;
                K([1 3],[1 3],2) = .7;
                K = K./sum(K(:));
                
                % number of slices to do at once
                nslice = min(max(5,floor(2^20/(8*res*res*nfactors(d)))),res);
                niter = floor(res./nslice);
                nover = res-(niter*nslice);
                
                % allocate some stuff
                contourmat(res+2,res+2,res+2) = 0;
                constrainpts = repmat(pt(:)',(res^2)*nslice,1);
                
                %>> codexpts = linspace(codedlims(Xax,2),codedlims(Xax,1),res);
                %>> codeypts = linspace(codedlims(Yax,1),codedlims(Yax,2),res);
                %>> codezpts = linspace(codedlims(Zax,1),codedlims(Zax,2),res);
                xpts = linspace(lims(Xax,2),lims(Xax,1),res);
                ypts = linspace(lims(Yax,1),lims(Yax,2),res);
                zpts = linspace(lims(Zax,1),lims(Zax,2),res);
                
                for n=1:niter
                    Zind = (1:nslice)+((n-1)*nslice);
                    
                    [Y,X,Z] = ndgrid(ypts,xpts,zpts(Zind)); %>> ndgrid(codeypts,codexpts,codezpts(Zind));
                    constrainpts(:,Xax)=X(:);
                    constrainpts(:,Yax)=Y(:);
                    constrainpts(:,Zax)=Z(:);
                    
                    contourmat(2:end-1,2:end-1,1+Zind) = ...
                        reshape(isInsideNoMemory(c,constrainpts),[res,res,nslice]);
                end
                
                
                % final smaller iteration if necessary
                if nover
                    Zind = (res-nover+1):res;
                    
                    [Y,X,Z] = ndgrid(ypts,xpts,zpts(Zind)); %>> ndgrid(codeypts,codexpts,codezpts(Zind));
                    constrainpts(1:length(X(:)),Xax)=X(:);
                    constrainpts(1:length(Y(:)),Yax)=Y(:);
                    constrainpts(1:length(Z(:)),Zax)=Z(:);
                    
                    contourmat(2:end-1,2:end-1,1+Zind)= ...
                        reshape(isInsideNoMemory(c,constrainpts(1:length(X(:)),:)),[res,res,nover]);
                end
                
                clear('constrainpts','X','Y','Z');
                
                contourmat = convn(contourmat,K,'same');
                
                [F, V] = isosurface(contourmat, ISOvalue);
                if ~isempty(V)
                    % interpolate x,y,z values of vertices without using interp3!
                    V(V<2) = 2;
                    V(V>(res+1)) = res+1;
                    V = (V-2)./(res-1);  % V is now 0 -> 1
                    V(:,1) = lims(Xax,2)+V(:,1)*(lims(Xax,1)-lims(Xax,2));
                    V(:,2) = lims(Yax,1)+V(:,2)*(lims(Yax,2)-lims(Yax,1));
                    V(:,3) = lims(Zax,1)+V(:,3)*(lims(Zax,2)-lims(Zax,1));
                    
                    % compute normals for the vertices
                    N = zeros(size(V));
                    [X,Y,Z] = meshgrid(xpts,ypts,zpts);   % necessary for interpolation
                    
                    G = zeros([res res res]);
                    f = contourmat(2:end-1,2:end-1,2:end-1);
                    
                    %% Y-DIR
                    diff = -2*(lims(Yax,2)-lims(Yax,1))./(res-1);
                    % Take forward differences on left and right edges
                    if res > 1
                        G(1,:) = 2*(f(2,:) - f(1,:))/diff;
                        G(res,:) = 2*(f(res,:) - f(res-1,:))/diff;
                    end
                    % Take centered differences on interior points
                    if res > 2
                        G(2:res-1,:) = (f(3:res,:)-f(1:res-2,:))./diff;
                    end
                    G = ipermute(G,[1 2 3]);
                    N(:,2)=interp3(X, Y, Z, G, V(:,1), V(:,2), V(:,3));
                    
                    f = permute(f,[2 3 1]);
                    
                    %% X-DIR
                    diff = 2*(lims(Xax,2)-lims(Xax,1))./(res-1);
                    % Take forward differences on left and right edges
                    if res > 1
                        G(1,:) = 2*(f(2,:) - f(1,:))/diff;
                        G(res,:) = 2*(f(res,:) - f(res-1,:))/diff;
                    end
                    % Take centered differences on interior points
                    if res > 2
                        G(2:res-1,:) = (f(3:res,:)-f(1:res-2,:))./diff;
                    end
                    G = ipermute(G,[2 3 1]);
                    N(:,1) = interp3(X, Y, Z, G, V(:,1), V(:,2), V(:,3));
                    
                    f = permute(f,[2 3 1]);
                    
                    %% Z-DIR
                    diff = -2*(lims(Zax,2)-lims(Zax,1))./(res-1);
                    % Take forward differences on left and right edges
                    if res > 1
                        G(1,:) = 2*(f(2,:) - f(1,:))/diff;
                        G(res,:) = 2*(f(res,:) - f(res-1,:))/diff;
                    end
                    % Take centered differences on interior points
                    if res > 2
                        G(2:res-1,:) = (f(3:res,:)-f(1:res-2,:))./diff;
                    end
                    G = ipermute(G,[3 1 2]);
                    N(:,3) = interp3(X, Y, Z, G, V(:,1), V(:,2), V(:,3));
                    
                else
                    N = [];
                end
                set(obj.hPatch,'Vertices',V, ...
                    'Faces',F, ...
                    'VertexNormals',N);
            end
            
            set(obj.hAxes,'XLim',lims(Xax,:),...
                'YLim',lims(Yax,:),...
                'ZLim',lims(Zax,:),...
                'XGrid','on','YGrid','on','ZGrid','on');
            
            set(obj.nodisplaytext,'String','');
        else
            mbcxlabel(obj.hAxes, '');
            mbcylabel(obj.hAxes, '');
            mbczlabel(obj.hAxes, '');
            set(obj.hPatch,'XData',NaN,'YData',NaN);
            set(obj.hAxes,'XLim',[0 1],'YLim',[0 1],'ZLim',[0 1], ...
                'XGrid','off','YGrid','off','ZGrid','off');
            set(obj.nodisplaytext,'String','3 or more factors required');
        end
        
        end  % pDrawGraph
        

        %----------------------------------------
        function pUpdate(obj, ~,~)
        %PUPDATE Update display
        %  PUPDATE(OBJ) refreshes the view's display.
        
        if obj.hasData
            obj.hSliceControl.Design = obj.MessageService.getdesign;
        else
            obj.hSliceControl.Design = [];
        end
        obj.pDrawGraph;
        
        end  % pUpdate
        
        %----------------------------------------
        function newobj = printCopy(obj, fig)
        %PRINTCOPY Create a new component for printing the component display
        %  NEWOBJ = PRINTCOPY(OBJ, FIG) creates and returns a handle to a new
        %  component, NEWOBJ, parented by the specified figure, FIG.  The new
        %  object will be used for printing a copy of the component OBJ.
        
        varinfo = printCopy(obj.hSliceControl, fig);
        
        % copy main axes
        ax = xregGui.HGPlotCopy(obj.hAxes, fig);
        set(ax, 'UIContextMenu', []);
        ax = mbcgui.widget.AxesContainer(...
            'AxesHandle', ax, ...
            'Border', [60 50 10 10]);
        
        layout = xreggridbaglayout(fig, ...
            'dimension',[1 2],...
            'colsizes',[130 -1],...
            'elements',{varinfo,ax});
        
        newobj = obj.addPrintTitle(layout);
        
        end  % printcopy
        
    end  % public methods
    
    methods (Access=protected)
        %----------------------------------------
        function pPostSetMessageService(obj)
        %PPOSTSETMESSAGESERVICE Respond to change of MessageService
        %  PPOSTSETMESSAGESERVICE(OBJ) is called when the MessageService property
        %  is changed.
        
        % Clear the listeners and add new ones
        obj.clearMessageServiceListeners;
        if ~isempty(obj.MessageService)
            L = event.listener(obj.MessageService,'ConstraintChange',@obj.pUpdate);
            addMessageServiceListener(obj,L)
        end
        obj.pUpdate;
        
        end  % pPostSetMessageService
    end
    
end  % classdef