1## Copyright (C) 2021 David Legland 2## All rights reserved. 3## 4## Redistribution and use in source and binary forms, with or without 5## modification, are permitted provided that the following conditions are met: 6## 7## 1 Redistributions of source code must retain the above copyright notice, 8## this list of conditions and the following disclaimer. 9## 2 Redistributions in binary form must reproduce the above copyright 10## notice, this list of conditions and the following disclaimer in the 11## documentation and/or other materials provided with the distribution. 12## 13## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' 14## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 17## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23## 24## The views and conclusions contained in the software and documentation are 25## those of the authors and should not be interpreted as representing official 26## policies, either expressed or implied, of the copyright holders. 27 28function varargout = drawCapsule(varargin) 29% Draw a capsule. 30% 31% drawCapsule(CAP) 32% Draws the capsule CAP on the current axis. 33% CAP is a 1-by-7 row vector in the form [x1 y1 z1 x2 y2 z2 r] where: 34% * [x1 y1 z1] are the coordinates of starting point, 35% * [x2 y2 z2] are the coordinates of ending point, 36% * R is the radius of the cylinder and the two semi-spheres at the ends 37% 38% drawCapsule(CAP, N) 39% Uses N points for discretizating the circles of the cylinder and the 40% semi-spheres (domes). Default value is 32. 41% 42% drawCapsule(..., 'FaceColor', COLOR) 43% Specifies the color of the capsule. Any couple of parameters name and 44% value can be given as argument, and will be transfered to the 'surf' 45% matlab function 46% 47% drawCapsule(..., 'FaceAlpha', ALPHA) 48% Specifies the transparency of the capsule and of the semi-spheres. 49% 50% drawCapsule(..., NAME, VALUE); 51% Specifies one or several options using parameter name-value pairs. 52% Available options are usual drawing options, as well as: 53% 'nPhi' the number of arcs used for drawing the meridians 54% (for the semi-spheres and the cylinder( 55% 'nTheta' the number of circles used for drawing the parallels 56% (only for the semi-spheres at the ends of the capsule) 57% 58% drawCapsule(AX, ...) 59% Specifies the axis to draw on. AX should be a valid axis handle. 60% 61% H = drawCapsule(...) 62% Returns a handle to the patch representing the capsule. 63% 64% 65% Examples: 66% % basic example 67% figure; drawCapsule([0 0 0 10 20 30 5]); 68% 69% % change capsule color 70% figure; drawCapsule([0 0 0 10 20 30 5], 'FaceColor', 'r'); 71% 72% % change capsule color using graphical handle 73% figure; 74% h = drawCapsule([0 0 0 10 20 30 5]); 75% set(h, 'facecolor', 'b'); 76% 77% % Draw three mutually intersecting capsules 78% p0 = [10 10 10]; 79% p1 = p0 + 80 * [1 0 0]; 80% p2 = p0 + 80 * [0 1 0]; 81% p3 = p0 + 80 * [0 0 1]; 82% figure; axis equal; axis([0 100 0 100 0 100]); hold on 83% drawCapsule([p0 p1 10], 'FaceColor', 'r'); 84% drawCapsule([p0 p2 10], 'FaceColor', 'g'); 85% drawCapsule([p0 p3 10], 'FaceColor', 'b'); 86% axis equal 87% set(gcf, 'renderer', 'opengl') 88% view([60 30]); light; 89% 90% % draw cube skeleton 91% [v, e, f] = createCube; 92% figure; axis equal; axis([-0.2 1.2 -0.2 1.2 -0.2 1.2]); hold on; view(3); 93% caps = [v(e(:,1), :) v(e(:,2),:) repmat(0.1, size(e, 1), 1)]; 94% drawCapsule(caps); 95% light 96% 97% % Draw a capsule with high resolution 98% figure; 99% h = drawCapsule([10,20,10,50,70,40,6], 'nPhi', 360, 'nTheta', 180); 100% l = light; view(3); 101% 102% 103% See Also: 104% crawCylinder, drawDome, drawSphere 105% 106 107% --------- 108% author: Moritz Schappler 109% created the 27/07/2013 110% 111 112% HISTORY 113% 2013-07-27 initial version as copy of drawCylinder 114% 2020-05-18 changes based on current version of geom3d 115 116 117%% Input argument processing 118 119% parse axis handle 120if isAxisHandle(varargin{1}) 121 hAx = varargin{1}; 122 varargin(1) = []; 123else 124 hAx = gca; 125end 126 127% input argument representing capsules 128cap = varargin{1}; 129varargin(1) = []; 130 131% process the case of multiple capsules 132if iscell(cap) 133 hCaps = gobjects(length(cap), 1); 134 for i = 1:length(cap) 135 hCaps(i) = drawCapsule(hAx, cap{i}, varargin{:}); 136 end 137 if nargout > 0 138 varargout{1} = hCaps; 139 end 140 return; 141elseif size(cap, 1) > 1 142 hCaps = gobjects(size(cap, 1), 3); 143 for i = 1:size(cap, 1) 144 hCaps(i,:) = drawCapsule(hAx, cap(i, :), varargin{:}); 145 end 146 147 if nargout > 0 148 varargout{1} = hCaps; 149 end 150 return; 151end 152 153faceColor = 'g'; 154ind = find(strcmpi(varargin, 'FaceColor'), 1, 'last'); 155if ~isempty(ind) 156 faceColor = varargin{ind+1}; 157 varargin(ind:ind+1) = []; 158end 159 160% extract transparency 161alpha = 1; 162ind = find(strcmpi(varargin, 'FaceAlpha'), 1, 'last'); 163if ~isempty(ind) 164 alpha = varargin{ind+1}; 165 varargin(ind:ind+1) = []; 166end 167 168% add default drawing options 169varargin = [{'FaceColor', faceColor, 'edgeColor', 'none', 'FaceAlpha', alpha} varargin]; 170 171% adjust drawing options for the cylinder. Options nPhi and nTheta may only 172% be given to the function drawDome, not drawCylinder 173options_cyl = ['open', varargin]; 174ind = find(strcmpi(options_cyl, 'nPhi'), 1, 'last'); 175if ~isempty(ind) 176 ind = ind(1); 177 nPhi = options_cyl{ind+1}; 178 options_cyl(ind:ind+1) = []; 179 options_cyl = [nPhi, options_cyl]; 180end 181ind = find(strcmpi(options_cyl, 'nTheta'), 1, 'last'); 182if ~isempty(ind) 183 options_cyl(ind:ind+1) = []; 184end 185 186hold on 187if all(cap(1:3) == cap(4:6)) 188 % the capsule is only a sphere. take arbitrary axis to be able to plot 189 cap(4:6) = cap(1:3)+eps*([0 0 1]); 190 h1 = 0; 191else 192 h1 = drawCylinder(cap, options_cyl{:}); 193end 194h2 = drawDome(cap([1:3,7]), (cap(1:3)-cap(4:6)), varargin{:}); 195h3 = drawDome(cap([4:6,7]), -(cap(1:3)-cap(4:6)), varargin{:}); 196 197% return handles 198if nargout == 1 199 varargout{1} = [h1, h2, h3]; 200end 201