如何防止物体被Matlab中的camlight照亮?

How to prevent an object from being illuminated by camlight in Matlab?

[以下是4个片段,有兴趣的应该只看前两个。然而,通过复制粘贴所有这些,应该能够启动我所看到的,尽管最后提供了屏幕截图。]

嗨,通过启动这个 main.m :

%To see if plotting a tick after setting camlight headlight will leads to
%its background becoming gray or not
%clear all
figure
arrow = arrow3D([0 0 0], [1 1 1], 'r', 0.8, 0.2, 1.5);
set(arrow, 'EdgeColor', 'interp', 'FaceColor', 'interp');
%camlight headlight %might be interesting to uncomment this line
pause(5)
surfaceHandle = rotateAxisTicks('lol','r',10,-0.3,0.5,0.5,1,1,1,0);
pause(5)
camlight headlight
%material(surfaceHandle,'default') %doesn't work
%surfaceHandle1.FaceLighting = 'none' %doesn't work

,它使用该函数 rotateAxisTicks.m

function surfaceHandle = rotateAxisTicks(str,color,fontsize,zmax,graduSpace,boxHeight,perc,labelNumber,axnumber,thetaInput)
%
    %zmax : give it a negative value to not overlap the axis
    %graduSpace : space between each graduation, within the projected on [0,1] axis if axis = x||y, OR local (not yet projected on x,y) axis !!
    %boxHeight : width of the boxes depend on how much the axis graduations are refined, so height shouldn't depend on graduSpace
    %perc : if perc = 1 (100%), then the labels are all sticked together with no space inbetween
    %labelNumber : the first tick to be displayed is actually associated to the second graduation (0 can't get several labels)
    %axnumber : out of nbParams, 1 for x, 2 for y, then, from closest to x, to closest to y : 3 to nbParams.
    %thetaInput : (angle around z, from x to the axis) has to be in degree

    %% Seems like there is no way to get rid of the black contouring...
    hFigure = figure(1000);
    set(hFigure,'Color', 'w', ...        % Create a figure window
                     'MenuBar', 'none', ...
                     'ToolBar', 'none');
    hText = uicontrol('Parent', hFigure, ...  % Create a text object
                      'Style', 'text', ...
                      'String', str, ...
                      'BackgroundColor', 'w', ...
                      'ForegroundColor', color, ...
                      'FontSize', fontsize, ...
                      'FontWeight', 'normal');
    set([hText hFigure], 'Pos', get(hText, 'Extent'));  %# Adjust the sizes of the
                                                        %#   text and figure
    imageData = getframe(hFigure);  %# Save the figure as an image frame
    delete(hFigure);
    textImage = imageData.cdata;  %# Get the RGB image of the text

    %% MAKE THE X,Y,Z (text) REVERSE DEPENDING ON AZIMUT VALUE (launch a fig and see on the bottom in real time the azimut value)
    % X or Y or Z(1,1) =  _______
    %                    *       |
    %                    |       |
    %                    |_______|
    % X or Y or Z(1,2) =  _______
    %                    |       *
    %                    |       |
    %                    |_______|
    % X or Y or Z(2,1) =  _______
    %                    |       |
    %                    |       |
    %                    x_______|
    % X or Y or Z(2,2) =  _______
    %                    |       |
    %                    |       |
    %                    |_______x
    if axnumber == 2 %axis = y
        X = [0 0; 0 0];
        Y = [0 perc*graduSpace; 0 perc*graduSpace] + labelNumber*graduSpace - perc*graduSpace/2;
        %(graduSpace/2)/2 to center under the graduation, (1-perc)/2) to
        %additionally shift a bit so that the perc% of graduSpace stay centered
        %under the graduation
    else %I assume axis = x, that I might later rotate if it's not actually x
        X = [0 perc*graduSpace; 0 perc*graduSpace] + labelNumber*graduSpace - perc*graduSpace/2; %+labelNumber*((graduSpace/2)+((1-perc)/2)*graduSpace)
        Y = [0 0; 0 0];
    end
    Z = [zmax zmax; zmax-boxHeight zmax-boxHeight];
    surfaceHandle = surf(X, Y, Z, 'FaceColor', 'texturemap', 'CData', textImage);
    if axnumber > 2
        rotate(surfaceHandle, [0 0 1], thetaInput,[0 0 0]);
    end
end

以及那个函数 arrow3D.m :

function arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio, cylRad, radRatioCone)

% arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
%     Used to plot a single 3D arrow with a cylindrical stem and cone arrowhead
%     pos = [X,Y,Z] - spatial location of the starting point of the arrow (end of stem)
%     deltaValues = [QX,QY,QZ] - delta parameters denoting the magnitude of the arrow along the x,y,z-axes (relative to 'pos')
%     colorCode - Color parameters as per the 'surf' command.  For example, 'r', 'red', [1 0 0] are all examples of a red-colored arrow
%     stemRatio - The ratio of the length of the stem in proportion to the arrowhead.  For example, a call of:
%                 arrow3D([0,0,0], [100,0,0] , 'r', 0.82) will produce a red arrow of magnitude 100, with the arrowstem spanning a distance
%                 of 82 (note 0.82 ratio of length 100) while the arrowhead (cone) spans 18.  
% 
%     Example:
%       arrow3D([0,0,0], [4,3,7]);  %---- arrow with default parameters
%       axis equal;
% 
%    Author: Shawn Arseneau
%    Created: September 14, 2006
%    Updated: September 18, 2006
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if nargin<2 || nargin>6    
        error('Incorrect number of inputs to arrow3D');     
    end
    if numel(pos)~=3 || numel(deltaValues)~=3
        error('pos and/or deltaValues is incorrect dimensions (should be three)');
    end
    if nargin<3                 
        colorCode = 'interp';                               
    end
    if nargin<4                 
        stemRatio = 0.75;                                   
    end    

    X = pos(1); %---- with this notation, there is no need to transpose if the user has chosen a row vs col vector
    Y = pos(2);
    Z = pos(3);

    [sphi, stheta, srho] = cart2sph(deltaValues(1), deltaValues(2), deltaValues(3));  

    %******************************************* CYLINDER == STEM *********************************************
    %cylinderRadius = 0.05*srho;
    cylinderRadius = cylRad;
    cylinderLength = srho*stemRatio;
    [CX,CY,CZ] = cylinder(cylinderRadius);
    CZ = CZ.*cylinderLength;    %---- lengthen

    %----- ROTATE CYLINDER
    [row, col] = size(CX);      %---- initial rotation to coincide with X-axis

    newEll = rotatePoints([0 0 -1], [CX(:), CY(:), CZ(:)]); %CX(:) actually reshape the 2xN matrices in a 2N vert vector, by vertically concatenating each column
    CX = reshape(newEll(:,1), row, col);
    CY = reshape(newEll(:,2), row, col);
    CZ = reshape(newEll(:,3), row, col);

    [row, col] = size(CX);    
    newEll = rotatePoints(deltaValues, [CX(:), CY(:), CZ(:)]);
    stemX = reshape(newEll(:,1), row, col);
    stemY = reshape(newEll(:,2), row, col);
    stemZ = reshape(newEll(:,3), row, col);

    %----- TRANSLATE CYLINDER
    stemX = stemX + X;
    stemY = stemY + Y;
    stemZ = stemZ + Z;

    %******************************************* CONE == ARROWHEAD *********************************************
    coneLength = srho*(1-stemRatio);
    coneRadius = cylinderRadius*radRatioCone;
    incr = 100;  %---- Steps of cone increments
    coneincr = coneRadius/incr;
    [coneX, coneY, coneZ] = cylinder(cylinderRadius*2:-coneincr:0);  %---------- CONE 
    coneZ = coneZ.*coneLength;

    %----- ROTATE CONE 
    [row, col] = size(coneX);    
    newEll = rotatePoints([0 0 -1], [coneX(:), coneY(:), coneZ(:)]);
    coneX = reshape(newEll(:,1), row, col);
    coneY = reshape(newEll(:,2), row, col);
    coneZ = reshape(newEll(:,3), row, col);

    newEll = rotatePoints(deltaValues, [coneX(:), coneY(:), coneZ(:)]);
    headX = reshape(newEll(:,1), row, col);
    headY = reshape(newEll(:,2), row, col);
    headZ = reshape(newEll(:,3), row, col);

    %---- TRANSLATE CONE
    V = [0, 0, srho*stemRatio];    %---- centerline for cylinder: the multiplier is to set the cone 'on the rim' of the cylinder
    Vp = rotatePoints([0 0 -1], V);
    Vp = rotatePoints(deltaValues, Vp);
    headX = headX + Vp(1) + X;
    headY = headY + Vp(2) + Y;
    headZ = headZ + Vp(3) + Z;
    %************************************************************************************************************    
    hStem = surf(stemX, stemY, stemZ, 'FaceColor', colorCode, 'EdgeColor', 'none');
    hold on
    hBottStem = fill3(stemX(1,:),stemY(1,:),stemZ(1,:), colorCode, 'EdgeColor', 'none');
    hold on
    hHead = surf(headX, headY, headZ, 'FaceColor', colorCode, 'EdgeColor', 'none');
    hold on
    hBottCone = fill3(headX(1,:),headY(1,:),headZ(1,:), colorCode, 'EdgeColor', 'none');

    if nargout==1   
        arrowHandle = [hStem, hBottStem, hHead, hBottCone]; 
    end

它本身使用该函数 rotatePoints.m :

function rotatedData = rotatePoints(alignmentVector, originalData)

% rotatedData = rotatePoints(alignmentVector, originalData) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
%     Rotate the 'originalData' in the form of Nx2 or Nx3 about the origin by aligning the x-axis with the alignment vector
% 
%       Rdata = rotatePoints([1,2,-1], [Xpts(:), Ypts(:), Zpts(:)]) - rotate the (X,Y,Z)pts in 3D with respect to the vector [1,2,-1]
% 
%       Rotating using spherical components can be done by first converting using [dX,dY,dZ] = cart2sph(theta, phi, rho);  alignmentVector = [dX,dY,dZ];
% 
% Example:
%   %% Rotate the point [3,4,-7] with respect to the following:
%   %%%% Original associated vector is always [1,0,0]
%   %%%% Calculate the appropriate rotation requested with respect to the x-axis.  For example, if only a rotation about the z-axis is
%   %%%% sought, alignmentVector = [2,1,0] %% Note that the z-component is zero
%   rotData = rotatePoints(alignmentVector, [3,4,-7]);
% 
%     Author: Shawn Arseneau
%     Created: Feb.2, 2006
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    alignmentDim = numel(alignmentVector); %number of elements in a matrix
    DOF = size(originalData,2); %---- DOF = Degrees of Freedom (i.e. 2 for two dimensional and 3 for three dimensional data)

    if alignmentDim~=DOF    
        error('Alignment vector does not agree with originalData dimensions');      
    end
    if DOF<2 || DOF>3      
        error('rotatePoints only does rotation in two or three dimensions');        
    end


    if DOF==2  % 2D rotation...        
        [rad_theta, rho] = cart2pol(alignmentVector(1), alignmentVector(2));    
        deg_theta = -1 * rad_theta * (180/pi);
        ctheta = cosd(deg_theta);  stheta = sind(deg_theta);

        Rmatrix = [ctheta, -1.*stheta;...
                   stheta,     ctheta];
        rotatedData = originalData*Rmatrix; 
        %assumption: rotate all the datas from the original base to the
        %base where the original x becomes alignmentVector

    else    % 3D rotation...        
        [rad_theta, rad_phi, rho] = cart2sph(alignmentVector(1), alignmentVector(2), alignmentVector(3));
        rad_theta = rad_theta * -1; 
        deg_theta = rad_theta * (180/pi);
        deg_phi = rad_phi * (180/pi); 
        ctheta = cosd(deg_theta);  stheta = sind(deg_theta); %MM : is it more accurate??
        Rz = [ctheta,   -1.*stheta,     0;...
              stheta,       ctheta,     0;...
              0,                 0,     1];                  %% First rotate as per theta around the Z axis
        rotatedData = originalData*Rz;

        [rotX, rotY, rotZ] = sph2cart(-1* (rad_theta+(pi/2)), 0, 1);          %% Second rotation corresponding to phi
        %assuming alignmentVector is the x for the new base, then the
        %hereabove argument corresponds to the y (z inversed)
        %the hereabove output = newX(in base 0) vectorial product -z(in base0)
        rotationAxis = [rotX, rotY, rotZ];
        u = rotationAxis(:)/norm(rotationAxis);        %% Code extract from rotate.m from MATLAB
        cosPhi = cosd(deg_phi);
        sinPhi = sind(deg_phi);
        invCosPhi = 1 - cosPhi;
        x = u(1);
        y = u(2);
        z = u(3);
        Rmatrix = [cosPhi+x^2*invCosPhi        x*y*invCosPhi-z*sinPhi     x*z*invCosPhi+y*sinPhi; ...
                   x*y*invCosPhi+z*sinPhi      cosPhi+y^2*invCosPhi       y*z*invCosPhi-x*sinPhi; ...
                   x*z*invCosPhi-y*sinPhi      y*z*invCosPhi+x*sinPhi     cosPhi+z^2*invCosPhi]';

        rotatedData = rotatedData*Rmatrix;        
    end

我最终得到:

虽然我想保留两个包含插入箭头的中间图:

和华丽的白色背景上的文字:

所以其实有两个问题:

1) 为什么调用我的文本刻度会禁用插值效果(颜色从蓝色变为黄色)?

2) 如何在不点亮我的勾选框的情况下保持 camlight? (即同时保持其背景为白色)

基本上应该只看前两段,后两段对我的问题没用。

非常感谢!

放在另一个axes

正如我在评论中所说,您有 2 个图形对象在同一个 axes 中,它们必须以完全不同的方式解释它们的 CData

我寻找的第一个选项是修改 arrow3drotateAxisTicks 中的一个,因此它们的图形对象将是 "compatible"(以颜色数据插值的方式轴),但它会非常密集,并且 3d 文本的方面必须不断 monitored/adjusted 对于图中的任何其他变化。

所以最简单的选择是经典的 MATLAB hack ...将图形对象放在不同的容器中(不同的 axes),然后将它们叠加在图形上,并匹配一些属性(限制、视图等) ...) 所以他们似乎只有一个。

开始了:

%% Draw your main arrow in the main figure
mainfig = figure ;
ax1     = axes ;
arrow = arrow3D([0 0 0], [1 1 1], 'r', 0.8, 0.2, 1.5);
set(arrow, 'EdgeColor', 'interp', 'FaceColor', 'interp');
camlight headlight

%% Draw your text in a temporary figure
tempfig = figure ;
ax2 = axes ;
surfaceHandle = rotateAxisTicks('lol','r',10,-0.3,0.5,0.5,1,1,1,0);
camlight headlight
%material(surfaceHandle,'default') %doesn't work
%surfaceHandle1.FaceLighting = 'none' %doesn't work

%% Prepare and set matching limits
xl = [ax1.XLim ; ax2.XLim] ;
xl = [min(xl(:,1)) , max(xl(:,2))] ;
yl = [ax1.YLim ; ax2.YLim] ;
yl = [min(yl(:,1)) , max(yl(:,2))] ;
zl = [ax1.ZLim ; ax2.ZLim] ;
zl = [min(zl(:,1)) , max(zl(:,2))] ;

hax = [ax1;ax2] ;
set(hax,'XLim',xl,'YLim',yl,'ZLim',zl)

% Adjust the view to be sure
ax2.View = ax1.View ;

%% Remove secondary axes background, then move it to main figure
ax2.Visible = 'off' ;   
ax2.Parent = mainfig ;
delete(tempfig)

%% link the view between axes
hl = linkprop( hax , 'View' ) ;
% or link even more properties at once
% hl = linkprop( hax , 'View' , 'XLim','YLim','ZLim') ;

这给你:


注意:您的 3d 箭头也由 2 个不同的图形对象(2x surf 和 2x patch)组成。当您设置 interp 模式时,不会渲染这 2 个补丁。您应该将 arrow3d 函数修改为 (a) 将 patch 对象更改为 surf 因此所有内容都是同一类型且兼容,或者 (b) 从函数中完全删除它们(如果它们没有呈现它们只是烦人......到处触发警告)。


编辑

这里是 arrow3d.m 的修改代码。我对其进行了更改,因此输出现在只有一个表面对象,更容易分配属性并且没有 patchsurf 之间不匹配的危险。我还简化了它,去掉了一些不需要的位,减少了表面所需的总点数。

有了这个你就得到了茎的底部和下锥体:

function arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio, cylRad )

% arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
%     Used to plot a single 3D arrow with a cylindrical stem and cone arrowhead
%     pos = [X,Y,Z] - spatial location of the starting point of the arrow (end of stem)
%     deltaValues = [QX,QY,QZ] - delta parameters denoting the magnitude of the arrow along the x,y,z-axes (relative to 'pos')
%     colorCode - Color parameters as per the 'surf' command.  For example, 'r', 'red', [1 0 0] are all examples of a red-colored arrow
%     stemRatio - The ratio of the length of the stem in proportion to the arrowhead.  For example, a call of:
%                 arrow3D([0,0,0], [100,0,0] , 'r', 0.82) will produce a red arrow of magnitude 100, with the arrowstem spanning a distance
%                 of 82 (note 0.82 ratio of length 100) while the arrowhead (cone) spans 18.  
% 
%     Example:
%       arrow3D([0,0,0], [4,3,7]);  %---- arrow with default parameters
%       axis equal;
% 
%    Author: Shawn Arseneau
%    Created: September 14, 2006
%    Updated: September 18, 2006
%
%    Updated: December 20, 2018
%       Tlab - refactored to have only one surface object as ouput
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if nargin<2 || nargin>6    
        error('Incorrect number of inputs to arrow3D');     
    end
    if numel(pos)~=3 || numel(deltaValues)~=3
        error('pos and/or deltaValues is incorrect dimensions (should be three)');
    end
    if nargin<3                 
        colorCode = 'interp';                               
    end
    if nargin<4                 
        stemRatio = 0.75;                                   
    end    
    Ncol = 21 ; % default number of column for the "cylinder.m" function

    X = pos(1); %---- with this notation, there is no need to transpose if the user has chosen a row vs col vector
    Y = pos(2);
    Z = pos(3);

    [~, ~, srho] = cart2sph(deltaValues(1), deltaValues(2), deltaValues(3));  

    %******************************************* CYLINDER == STEM *********************************************
    cylinderRadius = cylRad;
    cylinderLength = srho*stemRatio;
    [CX,CY,CZ] = cylinder(cylinderRadius,Ncol-1);
    CZ = CZ.*cylinderLength;    %---- lengthen

     %******************************************* CONE == ARROWHEAD *********************************************
    coneLength = srho*(1-stemRatio);
    [coneX, coneY, coneZ] = cylinder([cylinderRadius*2 0],Ncol-1);  %---------- CONE 
    coneZ = coneZ.*coneLength;
    % Translate cone on top of the stem cylinder
    coneZ = coneZ + cylinderLength ;

    % now close the bottom and add the cone to the stem cylinder surface
    bottom = zeros(1,Ncol) ;
    CX = [ bottom ; CX ; coneX ] ;
    CY = [ bottom ; CY ; coneY ] ;
    CZ = [ bottom ; CZ ; coneZ ] ;

    Nrow = size(CX,1);


    %----- ROTATE
    %---- initial rotation to coincide with X-axis
    newEll = rotatePoints([0 0 -1], [CX(:), CY(:), CZ(:)]); %CX(:) actually reshape the 2xN matrices in a 2N vert vector, by vertically concatenating each column
    CX = reshape(newEll(:,1), Nrow, Ncol);
    CY = reshape(newEll(:,2), Nrow, Ncol);
    CZ = reshape(newEll(:,3), Nrow, Ncol);

    newEll = rotatePoints(deltaValues, [CX(:), CY(:), CZ(:)]);
    stemX = reshape(newEll(:,1), Nrow, Ncol);
    stemY = reshape(newEll(:,2), Nrow, Ncol);
    stemZ = reshape(newEll(:,3), Nrow, Ncol);

    %----- TRANSLATE
    stemX = stemX + X;
    stemY = stemY + Y;
    stemZ = stemZ + Z;

    %----- DISPLAY
    hStem = surf(stemX, stemY, stemZ, 'FaceColor', colorCode, 'EdgeColor', 'none');

    %----- DISPLAY
    if nargout==1   
        arrowHandle = hStem ; 
    end