使用 PGF/TikZ 进行圆柱着色

使用 PGF/TikZ 进行圆柱着色

我正在尝试创建一个具有 3D 阴影效果的圆柱体。图片中的圆柱体垂直放置,有一个主体和一个末端。我希望主体被着色,以便它从圆柱体主体左侧的深色到中间的浅色(面向观察者)再到右侧的深色(浅色阴影效果)均匀变化。颜色在垂直方向上应保持不变。如果圆柱体末端也能如此那就太好了,但这并不那么重要。

我做了一些实验。下面的圆柱体 A 有一些阴影效果,但我不知道如何实现它。我甚至不知道将阴影用作节点的参数是否有意义,除非它显然在做一些事情。

圆柱体 B 与我想要的类似,除了阴影效果之外。

这是在 Debian squeeze 上使用 PGF 2.0 和 Tex Live 2009 进行测试的。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,decorations.fractals,shadows}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\begin{document}
\pagestyle{empty}
\begin{tikzpicture}    
\tikzset{draw, name=s, shape=cylinder, line width=0.1cm, shape
    border rotate=90, aspect=.2, inner xsep=3cm, inner ysep=2cm,
    cylinder uses custom fill, cylinder end fill=blue!25, cylinder
    body fill=blue!40};
  \node [aspect=0.25, shade={left color=red!20,right color=blue!50}] at (1,0) {A};
  \node[aspect=0.10] at (10,0) {B};
\end{tikzpicture}
\end{document}

答案1

为了创建独立圆柱体,而不使用预定义的 TikZ 形状,您可以执行以下操作:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\pagestyle{empty}
\begin{tikzpicture}    
   \coordinate (ll) at (-3,-2);
   \coordinate (lr) at (3,-2);
   \coordinate (ul) at (-3,2);
   \coordinate (ur) at (3,2);
   \shade [shading angle=90] (ll) arc (-180:-60:3cm and .75cm) -- +(0,4) arc (-60:-180:3cm and .75cm) -- cycle;
   \shade [shading angle=270] (lr) arc (0:-60:3cm and .75cm) -- +(0,4) arc (-60:0:3cm and .75cm) -- cycle;
   \draw [thick] (ll) arc (-180:0:3cm and .75cm) -- (ur) arc (0:-180:3cm and .75cm) -- cycle;
   \draw [thick, shade, shading angle=30] (ul) arc (-180:180:3cm and .75cm);
   \node at (0,-.75){\Huge A};
\end{tikzpicture}
\end{document} 

答案2

您可以使用预定义的圆柱形状,然后绘制一个顶部有实心填充的椭圆。使用以下代码,您可以cylinder像以前一样为形状提供所有选项,let椭圆中的代码负责处理椭圆的位置、大小和旋转。您只需调整颜色。

let \p<number> = (<coordinate>) in ... pgf 手册第 150 页(第 14.15 节)描述了该操作:它将由 描述的点分配(<coordinate>)给局部变量\p<number>,其中<number>可以任意选择。变量\x<number>\y<number>然后包含该点的 x 和 y 值。寄存器\n<number>可用于存储数学运算的结果。

该构造在手册的第 135 页(第 13.5.5 节)中描述:它描述从到 的<coordinate>!<number>!<second coordinate>线上的一点,其中 0 表示第一点,1 表示第二点,0.5 表示中间的一点。<first coordinate><second coordinate>

(cyl.before top)(cyl.after top)(cyl.top)由圆柱形状定义(参见 pgf 手册第 434 页第 48.3 节)。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,calc}
\begin{document}
\begin{tikzpicture}

\node [draw,
  shape=cylinder,
  name=nodename, % Can be defined arbitrarily
  alias=cyl, % Will be used by the ellipse to reference the cylinder
  aspect=1.5,
  minimum height=3cm,
  minimum width=2cm,
  left color=blue!30,
  right color=blue!60,
  middle color=red!20, % Has to be called after left color and middle color
  outer sep=-0.5\pgflinewidth, % to make sure the ellipse does not draw over the lines
  shape border rotate=90
] at (1,2) {A};

\fill [red!20] let
  \p1 = ($(cyl.before top)!0.5!(cyl.after top)$),
  \p2 = (cyl.top),
  \p3 = (cyl.before top),
  \n1={veclen(\x3-\x1,\y3-\y1)},
  \n2={veclen(\x2-\x1,\y2-\y1)},
  \n3={atan2((\y2-\y1),(\x2-\x1))}
 in 
  (\p1) ellipse [x radius=\n1, y radius = \n2, rotate=\n3];

\end{tikzpicture}
\end{document}

在此处输入图片描述


PGF 2.0 版本

对于 PGF 2.0,代码需要稍微进行调整,因为atan2旧版本中缺少数学函数并且椭圆的语法不同。

该操作let \p = () in ...在 pgf 2.0 手册(“Let 操作”)第 127 页(第 13.14 节)中进行了描述。

该构造<coordinate>!<number>!<coordinate>在 pgf 2.0 手册第 116 页第 12.4.3 节中进行了描述。

点 (cyl.before top)、(cyl.after top) 和 (cyl.top) 由圆柱形状定义(参见 pgf 2.0 手册第 326 页第 39.3 节(“几何形状”))。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,calc}
\begin{document}
\begin{tikzpicture}

\node [draw,
  shape=cylinder,
  name=nodename, % Can be defined arbitrarily
  alias=cyl, % Will be used by the ellipse to reference the cylinder
  aspect=1.5,
  minimum height=3cm,
  minimum width=2cm,
  left color=blue!30,
  right color=blue!60,
  middle color=red!20, % Has to be called after left color and middle color
  outer sep=-0.5\pgflinewidth, % to make sure the ellipse does not draw over the lines
  shape border rotate=90
] at (1,2) {A};

\fill [red!20] let
  \p1 = ($(cyl.before top)!0.5!(cyl.after top)$),
  \p2 = (cyl.top),
  \p3 = (cyl.before top),
  \n1={veclen(\x3-\x1,\y3-\y1)},
  \n2={veclen(\x2-\x1,\y2-\y1)}
 in 
  (\p1) ellipse (\n1 and \n2);

\end{tikzpicture}
\end{document}

答案3

只是为了好玩。上面的答案很棒。然而,Jan 的回答没有创建节点。杰克的精彩回答分两步构造椭圆。这根本不是坏事,但有人可能想一次性构造它。这里有一个一步完成的方法。我没有想出结束的路径,而是从库中复制的。似乎可以shapes.geometric(滥用)使用路径图片来“托管”一些可以在其他地方找到的 pgf 代码。我不知道这个网站之前是否提到过这一点,如果是的话,我很乐意给予适当的赞扬,我也不知道是否存在重大陷阱。我只做了非常有限的测试,所以请小心使用它。

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes.geometric}
\begin{document}
\tikzset{cylinder end fill/.style={path picture={
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%  
\pgfpathmoveto{\beforetop}%
\pgfpatharc{90}{-270}{\xradius and \yradius}%
\pgfpathclose
\pgfsetfillcolor{#1}%
\pgfusepath{fill}}
}}
\begin{tikzpicture}
\pgfmathsetmacro{\myaspect}{pi/4}
\node [draw,
  shape=cylinder,
  aspect=\myaspect,
  minimum height=3cm,
  minimum width=2cm,
  rotate=20,
  cylinder end fill=blue,
  left color=blue!30,
  right color=black,
  middle color=blue!80,
  shading angle=20,
  font=\sffamily,
  text width=pi*1cm,
  text=white]  {Hello world, ducks, koalas and marmots!};
\end{tikzpicture}
\end{document}

在此处输入图片描述

旧答案:(不必要的复杂)在这个答案中,基于标准圆柱体声明了一个“新”形状。我没有对其进行广泛的测试,我只是为了学习一些新东西。我学到的新东西在答案的上半部分。

\documentclass{beamer}
\setbeamertemplate{navigation symbols}{}
\usepackage{tikz} 
\usetikzlibrary{shapes.geometric}
\makeatletter

% Additional keys for shape "shaded cylinder"
%
% /pgf/cylinder body top shade  : Custom shading color for the cylinderbody.
% /pgf/cylinder body middle shade: Custom shading color for the cylinderbody.
% /pgf/cylinder body bottom shade : Custom shading color for the cylinderbody.
%


\newif\ifpgfcylinderusescustomshade
\pgfkeys{/pgf/.cd,
    cylinder uses custom shade/.is if=pgfcylinderusescustomshade,
    cylinder end fill/.initial=white,
    cylinder body top shade/.initial=white,
    cylinder body middle shade/.initial=white,
    cylinder body bottom shade/.initial=white,
    cylinder body shade angle/.initial=0,
}



\pgfdeclareshape{shaded cylinder}{%
    \savedmacro\getcylinderpoints{%
        \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
        \pgf@x\pgf@xc%
        \advance\[email protected]\wd\pgfnodeparttextbox%
        \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
        \pgf@y\pgf@yc%
        \advance\[email protected]\ht\pgfnodeparttextbox%
        \advance\[email protected]\dp\pgfnodeparttextbox%
        \ifpgfshapeborderusesincircle%
            \pgfmathsetmacro\rotate{\pgfkeysvalueof{/pgf/shape border rotate}}%
            \ifdim\pgf@x<\pgf@y%
                \pgf@x\pgf@y%
            \else%
                \pgf@y\pgf@x%
            \fi%
            \[email protected]\pgf@x%
            \[email protected]\pgf@y%           
        \else%
            \pgfmathmod{\pgfkeysvalueof{/pgf/shape border rotate}}{360}%
            \ifdim\pgfmathresult pt<0pt\relax%
                \pgfmathadd@{\pgfmathresult}{360}%
            \fi%
            \pgfmathsetcount\c@pgf@counta{+\pgfmathresult}%
            \advance\c@pgf@counta45\relax%
            \divide\c@pgf@counta90\relax%
            \multiply\c@pgf@counta90\relax%
            \edef\rotate{\the\c@pgf@counta}%
            \ifnum\c@pgf@counta=90\relax%
                \pgf@xa\pgf@x%
                \pgf@x\pgf@y%
                \pgf@y\pgf@xa%
                \pgf@yc\pgf@xc%
            \else%
                \ifnum\c@pgf@counta=270\relax%
                    \pgf@xa\pgf@x%
                    \pgf@x\pgf@y%
                    \pgf@y\pgf@xa%
                    \pgf@yc\pgf@xc%
                \fi%
            \fi%
        \fi%
        \addtosavedmacro\rotate%
        \pgf@xa\pgf@x%
        \pgf@ya\pgf@y%
        \pgfutil@tempdima\pgfshapeaspect\pgf@ya%
        \pgfutil@tempdimb\pgf@ya%
        %
        % Adjust for minimum height.
        %
        \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
        \ifdim\pgfutil@tempdimb<.5\pgf@xc\relax%
            \[email protected]\pgf@xc%
            \pgf@ya\pgfutil@tempdimb%
        \fi%
        %
        % Calculate how far the node contents can extend into the cylinder bottom.
        %
        \pgf@yb\pgfutil@tempdimb%
        \advance\pgf@yb-\pgf@yc%
        \pgfmathdivide@{\pgfmath@tonumber{\pgf@yb}}{\pgfmath@tonumber{\pgfutil@tempdimb}}%
        \pgfmathasin@{\pgfmathresult}%
        \pgfmathcos@{\pgfmathresult}%
        \let\angle\pgfmathresult%
        \pgf@xb\pgfmathresult\pgfutil@tempdima%
        %
        % Adjust for minimum width.
        %
        \[email protected]\pgflinewidth%
        \advance\[email protected]\pgf@xa%
        \advance\[email protected]\pgfutil@tempdima%
        \advance\pgf@x-\pgf@xb%
        \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum height}}%
        \ifdim\pgf@x<\pgf@xc%
            \advance\pgf@xc-\pgf@x%
            \advance\[email protected]\pgf@xc%
        \fi%        
        %
        % Add the larger of the outer sep to the radii.
        %
        \pgf@x\pgfutil@tempdima\relax%
        \pgf@y\pgfutil@tempdimb\relax%
        \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/outer xsep}}%
        \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}%
        \ifdim\pgf@xc>\pgf@yc%
            \advance\pgf@x\pgf@xc%
            \advance\pgf@y\pgf@xc%
            \edef\outersep{\the\pgf@xc}%
        \else%
            \advance\pgf@x\pgf@yc%
            \advance\pgf@y\pgf@yc%
            \edef\outersep{\the\pgf@yc}%
        \fi%
        \edef\xradius{\the\pgf@x}%
        \edef\yradius{\the\pgf@y}%
        \addtosavedmacro\xradius%
        \addtosavedmacro\yradius%
        \addtosavedmacro\outersep%
        %
        \pgfextract@process\cylindercenter{%
            \pgf@x\pgfutil@tempdima%
            \advance\[email protected]\pgflinewidth%
            \advance\pgf@x\pgf@xb%
            \[email protected]\pgf@x% 
            \pgf@y0pt%
        }%
        \addtosavedmacro\cylindercenter%
        %
        \pgfextract@process\beforetop{%
            \pgf@x\pgf@xa%
            \advance\pgf@x\pgfutil@tempdima%
            \advance\[email protected]\pgflinewidth%
            \pgf@y\pgf@ya%
        }%
        \pgfextract@process\afterbottom{%
            \pgf@x-\pgf@xa%
            \advance\pgf@x\pgf@xb%
            \pgf@y\pgf@ya%
        }%
        \addtosavedmacro\beforetop%
        \addtosavedmacro\afterbottom%       
        \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}%
        \pgfextract@process\beforetopanchor{%
            \beforetop%
            \advance\pgf@y\pgf@yc%
        }%
        \pgfextract@process\afterbottomanchor{%
            \afterbottom%
            \advance\pgf@y\pgf@yc%
        }%
        \addtosavedmacro\beforetopanchor%       
        \addtosavedmacro\afterbottomanchor% 
        %
        \beforetopanchor%
        \advance\pgf@x\xradius\relax%
        \ifdim\pgf@x>\pgf@y%
            \edef\externalradius{\the\pgf@x}%
        \else%
            \edef\externalradius{\the\pgf@y}%
        \fi%
        \addtosavedmacro\externalradius%
    }
    \savedanchor\centerpoint{%
        \[email protected]\wd\pgfnodeparttextbox%
        \[email protected]\ht\pgfnodeparttextbox%
        \advance\[email protected]\dp\pgfnodeparttextbox%
    }%
    \savedanchor\midpoint{%
        \[email protected]\wd\pgfnodeparttextbox%
        \pgfmathsetlength\pgf@y{+0.5ex}%
    }%
    \savedanchor\basepoint{%
        \[email protected]\wd\pgfnodeparttextbox%
        \pgf@y0pt%
    }%
    \anchor{center}{\centerpoint}
    \anchor{shape center}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{\pgfpointadd{\cylindercenter}{\centerpoint}}%
            {\centerpoint}{\rotate}%    
    }%
    \anchor{mid}{\midpoint}%
    \anchor{mid east}{%
        \getcylinderpoints%
        \let\pgf@cylinder@referencepoint\midpoint%
        \pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{0pt}}%
    }%
    \anchor{mid west}{%
        \getcylinderpoints%
        \let\pgf@cylinder@referencepoint\midpoint%
        \pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{0pt}}%
    }%
    \anchor{base}{\basepoint}%
    \anchor{base east}{%
        \getcylinderpoints%
        \let\pgf@cylinder@referencepoint\basepoint%
        \pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{0pt}}%
    }%
    \anchor{base west}{%
        \getcylinderpoints%
        \let\pgf@cylinder@referencepoint\basepoint%
        \pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{0pt}}%
    }%
    \anchor{north}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{0pt}{\externalradius}}%
    }%
    \anchor{south}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{0pt}{-\externalradius}}%
    }%
    \anchor{east}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{0pt}}%
    }%
    \anchor{west}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{0pt}}%
    }%
    \anchor{north east}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{\externalradius}}%
    }%
    \anchor{south west}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{-\externalradius}}%
    }%
    \anchor{south east}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{-\externalradius}}%
    }%
    \anchor{north west}{%
        \getcylinderpoints%
        \pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{\externalradius}}%
    }%
    \anchor{before top}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor}{\centerpoint}}{\centerpoint}{\rotate}%
    }
    \anchor{top}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{%
            \pgfpointadd{%
                \beforetop%
                \pgf@y0pt\relax%
                \advance\pgf@x\xradius\relax%
            }{\centerpoint}}{\centerpoint}{\rotate}%
    }
    \anchor{after top}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor\pgf@y-\pgf@y}{\centerpoint}}{\centerpoint}{\rotate}%
    }
    \anchor{before bottom}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor\pgf@y-\pgf@y}{\centerpoint}}{\centerpoint}{\rotate}%
    }
    \anchor{bottom}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{%
            \pgfpointadd{%
                \afterbottom%
                \pgf@y0pt\relax%
                \advance\pgf@x-\xradius\relax%
            }{\centerpoint}}{\centerpoint}{\rotate}%
    }
    \anchor{after bottom}{%
        \getcylinderpoints%
        \pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor}{\centerpoint}}{\centerpoint}{\rotate}%
    }   
    \backgroundpath{%
        \getcylinderpoints%
        {%
            \pgf@x\xradius\relax%
            \advance\pgf@x-\outersep\relax%
            \edef\xradius{\the\pgf@x}%
            \pgf@y\yradius\relax%
            \advance\pgf@y-\outersep\relax%
            \edef\yradius{\the\pgf@y}%
            \pgftransformshift{\centerpoint}%
            \pgftransformrotate{\rotate}%
            \pgfpathmoveto{\afterbottom}%
            \pgfpatharc{90}{270}{\xradius and \yradius}%
            \pgfpathlineto{\beforetop\pgf@y-\pgf@y}%
            \pgfpatharc{-90}{90}{\xradius and \yradius}%
            \pgfpathclose%
            \pgfpathmoveto{\beforetop}%
            \pgfpatharc{90}{270}{\xradius and \yradius}%
        }%
    }%
    \behindbackgroundpath{%
        \ifpgfcylinderusescustomfill%
            \getcylinderpoints%
            \pgf@x\xradius\relax%
            \advance\pgf@x-\outersep\relax%
            \edef\xradius{\the\pgf@x}%
            \pgf@y\yradius\relax%
            \advance\pgf@y-\outersep\relax%
            \edef\yradius{\the\pgf@y}%
            {%              
                \pgftransformshift{\centerpoint}%
                \pgftransformrotate{\rotate}%
                \pgfpathmoveto{\afterbottom}%
                \pgfpatharc{90}{270}{\xradius and \yradius}%
                \pgfpathlineto{\beforetop\pgf@y-\pgf@y}%
                \pgfpatharc{270}{90}{\xradius and \yradius}%
                \pgfpathclose%
                \expandafter\pgfsetfillcolor\expandafter{\pgfkeysvalueof{/pgf/cylinder body fill}}%
                \pgfusepath{fill}%
                %
                \pgfpathmoveto{\beforetop}%
                \pgfpatharc{90}{-270}{\xradius and \yradius}%
                \pgfpathclose
                \expandafter\pgfsetfillcolor\expandafter{\pgfkeysvalueof{/pgf/cylinder end fill}}%
                \pgfusepath{fill}%
            }%      
        \fi%    
        \ifpgfcylinderusescustomshade%
            \getcylinderpoints%
            \pgf@x\xradius\relax%
            \advance\pgf@x-\outersep\relax%
            \edef\xradius{\the\pgf@x}%
            \pgf@y\yradius\relax%
            \advance\pgf@y-\outersep\relax%
            \edef\yradius{\the\pgf@y}%
            {%                  
                %
                \expandafter\pgfdeclareverticalshading{cylindershade}{\yradius}
                    {color(0bp)=(\expandafter{\pgfkeysvalueof{/pgf/cylinder body top shade}});
                    color(0.5*\yradius)=(\expandafter{\pgfkeysvalueof{/pgf/cylinder body middle shade}});  
                    color(\yradius)=(\expandafter{\pgfkeysvalueof{/pgf/cylinder body bottom shade}})}           
                \pgftransformshift{\centerpoint}%
                \pgftransformrotate{\rotate}%
                \begin{pgfscope}%   
                \pgfpathmoveto{\afterbottom}%
                \pgfpatharc{90}{270}{\xradius and \yradius}%
                \pgfpathlineto{\beforetop\pgf@y-\pgf@y}%
                \pgfpatharc{270}{90}{\xradius and \yradius}%
                \pgfpathclose%
                \typeout{\pgfkeysvalueof{/pgf/cylinder body shade angle}}
                \expandafter\pgfshadepath{cylindershade}{\pgfkeysvalueof{/pgf/cylinder body shade angle}}%
                \pgfsetfillcolor{white}%
                \pgfsetfillopacity{0}%
                \pgfusepath{fill}%
                \end{pgfscope}
                %
                \pgfpathmoveto{\beforetop}%
                \pgfpatharc{90}{-270}{\xradius and \yradius}%
                \pgfpathclose
                \expandafter\pgfsetfillcolor\expandafter{\pgfkeysvalueof{/pgf/cylinder end fill}}%
                \pgfusepath{fill}%
            }%      
        \fi%    
    }%
    \anchorborder{%
        \pgfextract@process\externalpoint{}%
        \getcylinderpoints%
        \pgfutil@ifundefined{pgf@cylinder@referencepoint}{\let\referencepoint\centerpoint}{%
            \let\referencepoint\pgf@cylinder@referencepoint}%
        \pgfextract@process\externalpoint{%
            \externalpoint%
            \pgf@xa\pgf@x%
            \pgf@ya\pgf@y%
            \referencepoint%
            \advance\pgf@x\pgf@xa%
            \advance\pgf@y\pgf@ya%
        }%
        \pgfmathanglebetweenpoints{\centerpoint}{\externalpoint}%
        \pgfmathsubtract@{\pgfmathresult}{\rotate}%
        \ifdim\pgfmathresult pt<0pt\relax%
            \pgfmathadd@{\pgfmathresult}{360}%
        \fi%
        \let\externalangle\pgfmathresult%
        %
        \pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\afterbottomanchor}{\centerpoint}}%
        \ifdim\externalangle pt<\pgfmathresult pt\relax%
            \pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\beforetopanchor}{\centerpoint}}%
            \ifdim\externalangle pt<\pgfmathresult pt\relax%
                \pgfmathrotatepointaround{%
                    \pgfmathpointintersectionoflineandarc%
                        {\pgfmathrotatepointaround{\externalpoint}{\centerpoint}{-\rotate}}%
                        {\pgfmathrotatepointaround{\referencepoint}{\centerpoint}{-\rotate}}%
                        {%
                            \beforetop%
                            \pgf@xa\pgf@x%
                            \centerpoint%
                            \advance\pgf@x\pgf@xa%
                        }%
                        {0}{90}{\xradius and \yradius}%
                    }{\centerpoint}{\rotate}%
            \else%
                \pgfpointintersectionoflines{%
                    \pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor}{\centerpoint}}%
                        {\centerpoint}{\rotate}}{%
                    \pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor}{\centerpoint}}%
                        {\centerpoint}{\rotate}}%
                    {\referencepoint}{\externalpoint}%
            \fi%
        \else%
            \pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\afterbottomanchor\pgf@y-\pgf@y}{\centerpoint}}%
            \ifdim\externalangle pt>\pgfmathresult pt\relax%
                \pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\beforetopanchor\pgf@y-\pgf@y}{\centerpoint}}%
                \ifdim\externalangle pt>\pgfmathresult pt\relax%
                    \pgfmathrotatepointaround{%
                        \pgfmathpointintersectionoflineandarc%
                            {\pgfmathrotatepointaround{\externalpoint}{\centerpoint}{-\rotate}}%
                            {\pgfmathrotatepointaround{\referencepoint}{\centerpoint}{-\rotate}}%
                            {%
                                \beforetop%
                                \pgf@xa\pgf@x%
                                \centerpoint
                                \advance\pgf@x\pgf@xa%
                            }%
                            {270}{360}{\xradius and \yradius}%
                        }{\centerpoint}{\rotate}%
                \else%
                    \pgfpointintersectionoflines{%
                        \pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor\pgf@y-\pgf@y}{\centerpoint}}%
                            {\centerpoint}{\rotate}}{%
                        \pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor\pgf@y-\pgf@y}{\centerpoint}}%
                            {\centerpoint}{\rotate}}%
                        {\referencepoint}{\externalpoint}%
                \fi%
            \else%
                \pgfmathrotatepointaround{%
                    \pgfmathpointintersectionoflineandarc%
                        {\pgfmathrotatepointaround{\externalpoint}{\centerpoint}{-\rotate}}%
                        {\pgfmathrotatepointaround{\referencepoint}{\centerpoint}{-\rotate}}%
                        {%
                            \afterbottom%
                            \pgf@xa\pgf@x%
                            \centerpoint
                            \advance\pgf@x\pgf@xa%
                        }%
                        {90}{270}{\xradius and \yradius}%
                    }{\centerpoint}{\rotate}%
            \fi%
        \fi%
    }
}
\makeatother



\begin{document}
\begin{frame}[t]
\frametitle{}
\begin{tikzpicture}[scale=1., transform shape]
\node [rotate=30,shaded cylinder,draw,thick,aspect=2.,minimum height=5cm,
minimum width=4cm,shape border rotate=30,cylinder uses custom shade, 
cylinder body top shade=black,
cylinder body middle shade=blue,
cylinder body bottom shade=blue!30,
cylinder body shade angle=30,
cylinder end fill=blue,text=white,font=\large
] at (0,0){Hello world, how are you doing!};
\end{tikzpicture}
\end{frame}
\end{document} 

在此处输入图片描述

相关内容