0001 function varargout = drawArrow3d(pos, vec, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 if numel(pos) == 1 && ishghandle(pos, 'axes')
0048 hAx = pos;
0049 pos=vec;
0050 vec=varargin{1};
0051 varargin(1)=[];
0052 else
0053 hAx = gca;
0054 end
0055
0056 numArrows = size(pos,1);
0057 if numArrows ~= size(vec,1)
0058 error(['Number of rows of position and magnitude inputs do not agree. ' ...
0059 'Type ''help drawArrow3d'' for details']);
0060 end
0061
0062
0063 p = inputParser;
0064 p.KeepUnmatched = true;
0065 isPointArray3d = @(x) validateattributes(x,{'numeric'},...
0066 {'nonempty','nonnan','real','finite','size',[nan,3]});
0067 addRequired(p,'pos',isPointArray3d)
0068 addRequired(p,'vec',isPointArray3d);
0069 addOptional(p,'color', 'k', @(x) validateColor(x, numArrows));
0070 isStemRatio = @(x) validateattributes(x,{'numeric'},{'vector','>', 0, '<', 1});
0071 addParameter(p,'stemRatio', 0.75, isStemRatio);
0072 isArrowRadius = @(x) validateattributes(x,{'numeric'},{'scalar','>=', 0.01, '<=', 0.1});
0073 addParameter(p,'arrowRadius',0.025, isArrowRadius);
0074
0075 parse(p,pos,vec,varargin{:});
0076 pos = p.Results.pos;
0077 vec = p.Results.vec;
0078 [~, color] = validateColor(p.Results.color, numArrows);
0079 stemRatio = p.Results.stemRatio;
0080 if numel(stemRatio) == 1; stemRatio = repmat(stemRatio,numArrows,1); end
0081 arrowRadius = p.Results.arrowRadius;
0082 if numel(arrowRadius) == 1; arrowRadius = repmat(arrowRadius,numArrows,1); end
0083 drawOptions=p.Unmatched;
0084
0085
0086 hold(hAx,'on')
0087 qHandle=gobjects(numArrows,1);
0088 for i=1:numArrows
0089 qHandle(i) = drawSingleVector3d(hAx, pos(i,:), vec(i,:), color(i,:), ...
0090 stemRatio(i),arrowRadius(i),drawOptions);
0091 end
0092
0093 if nargout > 0
0094 varargout = {qHandle};
0095 end
0096
0097 end
0098
0099 function [valid, color]=validateColor(color,numArrows)
0100 valid=true;
0101 [arrowRow, arrowCol] = size(color);
0102 if arrowRow==1
0103 if ischar(color)
0104 color=repmat(color,numArrows,1);
0105 else
0106 if arrowCol~=3
0107 error('color in RGBvalue must be of the form 1x3.');
0108 end
0109 color=repmat(color,numArrows,1);
0110 end
0111 elseif arrowRow~=numArrows
0112 error('color in RGBvalue must be of the form Nx3.');
0113 end
0114
0115 end
0116
0117 function arrowHandle = drawSingleVector3d(hAx, pos, vec, color, stemRatio, arrowRadius, drawOptions)
0118
0119
0120
0121
0122 X = pos(1); Y = pos(2); Z = pos(3);
0123
0124 [~, ~, srho] = cart2sph(vec(1), vec(2), vec(3));
0125
0126
0127 cylinderRadius = srho*arrowRadius;
0128 cylinderLength = srho*stemRatio;
0129 [CX,CY,CZ] = cylinder(cylinderRadius);
0130 CZ = CZ.*cylinderLength;
0131
0132
0133 [row, col] = size(CX);
0134
0135 newEll = transformPoint3d([CX(:), CY(:), CZ(:)],createRotationVector3d([1 0 0],[0 0 -1]));
0136 CX = reshape(newEll(:,1), row, col);
0137 CY = reshape(newEll(:,2), row, col);
0138 CZ = reshape(newEll(:,3), row, col);
0139
0140 [row, col] = size(CX);
0141 newEll = transformPoint3d([CX(:), CY(:), CZ(:)],createRotationVector3d([1 0 0],vec));
0142 stemX = reshape(newEll(:,1), row, col);
0143 stemY = reshape(newEll(:,2), row, col);
0144 stemZ = reshape(newEll(:,3), row, col);
0145
0146
0147 stemX = stemX + X;
0148 stemY = stemY + Y;
0149 stemZ = stemZ + Z;
0150
0151
0152 RADIUS_RATIO = 1.5;
0153 coneLength = srho*(1-stemRatio);
0154 coneRadius = cylinderRadius*RADIUS_RATIO;
0155 incr = 4;
0156 coneincr = coneRadius/incr;
0157 [coneX, coneY, coneZ] = cylinder(cylinderRadius*2:-coneincr:0);
0158 coneZ = coneZ.*coneLength;
0159
0160
0161 [row, col] = size(coneX);
0162 newEll = transformPoint3d([coneX(:), coneY(:), coneZ(:)],createRotationVector3d([1 0 0],[0 0 -1]));
0163 coneX = reshape(newEll(:,1), row, col);
0164 coneY = reshape(newEll(:,2), row, col);
0165 coneZ = reshape(newEll(:,3), row, col);
0166
0167 newEll = transformPoint3d([coneX(:), coneY(:), coneZ(:)],createRotationVector3d([1 0 0],vec));
0168 headX = reshape(newEll(:,1), row, col);
0169 headY = reshape(newEll(:,2), row, col);
0170 headZ = reshape(newEll(:,3), row, col);
0171
0172
0173
0174 V = [0, 0, srho*stemRatio];
0175 Vp = transformPoint3d(V,createRotationVector3d([1 0 0],[0 0 -1]));
0176 Vp = transformPoint3d(Vp,createRotationVector3d([1 0 0],vec));
0177 headX = headX + Vp(1) + X;
0178 headY = headY + Vp(2) + Y;
0179 headZ = headZ + Vp(3) + Z;
0180
0181
0182 hStem = patch(hAx, surf2patch(stemX, stemY, stemZ), 'FaceColor', color, 'EdgeColor', 'none', drawOptions);
0183 hold(hAx,'on')
0184 hHead = patch(hAx, surf2patch(headX, headY, headZ), 'FaceColor', color, 'EdgeColor', 'none', drawOptions);
0185 arrowHandle = hggroup(hAx);
0186 set([hStem, hHead],'Parent',arrowHandle);
0187
0188 end