如何防止物体被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
。
我寻找的第一个选项是修改 arrow3d
或 rotateAxisTicks
中的一个,因此它们的图形对象将是 "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
的修改代码。我对其进行了更改,因此输出现在只有一个表面对象,更容易分配属性并且没有 patch
和 surf
之间不匹配的危险。我还简化了它,去掉了一些不需要的位,减少了表面所需的总点数。
有了这个你就得到了茎的底部和下锥体:
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
[以下是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
。
我寻找的第一个选项是修改 arrow3d
或 rotateAxisTicks
中的一个,因此它们的图形对象将是 "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
的修改代码。我对其进行了更改,因此输出现在只有一个表面对象,更容易分配属性并且没有 patch
和 surf
之间不匹配的危险。我还简化了它,去掉了一些不需要的位,减少了表面所需的总点数。
有了这个你就得到了茎的底部和下锥体:
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