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