更新

更新

Asymptote 在绘制三维图形时确实会给出 3D 箭头(它们甚至有阴影!)。我们能用 TikZ 伪造它吗?这是一个手写的示例,只有一个箭头:

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}[->,scale=2]
  \draw[>={Triangle[width=3pt,length=5pt]}] (0,0,0) -- (1,0,0);
  \draw[>={Triangle[width=3pt,length=5pt]}] (0,0,0) -- (0,1,0);
  \draw[>={Circle[sep=-.9pt,width=3.08pt,length=2pt]Triangle[width=3pt,length=5pt]}] (0,0,0) -- (0,0,1);
\end{tikzpicture}
\end{document}

在此处输入图片描述

但这是(错误地)通过反复试验手动计算出来的(除了它并不完美之外,看看其他两个轴 — x 和 y — 的方向,它应该有一定的倾斜度)。如果有一个像其他箭头一样的界面就好了

>={3D[length=⟨real length⟩,width=⟨real width of the base⟩]}

然后根据这些值进行计算(当然,也会考虑到x=⟨x vect⟩,y=⟨y vect⟩,z=⟨z vect⟩

Circle[sep=⟨value⟩,width=⟨value⟩,length=⟨value⟩,slant=⟨value⟩]
Triangle[width=⟨value⟩,length=⟨value⟩] % And I'm not sure if `slant=⟨value⟩`
                                       % is necessary in this Triangle case

例子

使用答案中的代码(感谢 Symbol1),例如,此代码(从另一个问题中获取想法,链接在评论中)

\begin{tikzpicture}[x={(0cm,1cm)},
                    y={({cos(30)*1cm},{sin(30)*-1cm})},
                    z={({cos(20)*1cm},{sin(20)*1cm})},
                    thick,
                    scale=3]
  \pgfmathsetmacro{\ax}{.4}
  \pgfmathsetmacro{\ay}{.6}
  \pgfmathsetmacro{\az}{-.6}
  \pgfmathsetmacro{\bx}{.4}
  \pgfmathsetmacro{\by}{-.7}
  \pgfmathsetmacro{\bz}{-.8}
  \draw[densely dotted,thin] (\ax,\ay,\az) -- (\ax,0,\az);
  \draw[densely dotted,thin] (\ax,\ay,\az) -- (0,\ay,\az);
  \draw[densely dotted,thin] (\ax,0,0) -- (\ax,0,\az) -- (0,0,\az);
  \draw[densely dotted,thin] (0,0,\az) -- (0,\ay,\az) -- (0,\ay,0);
  \draw[densely dotted,thin] (\bx,\by,\bz) -- (\bx,0,\bz);
  \draw[densely dotted,thin] (\bx,\by,\bz) -- (0,\by,\bz);
  \draw[densely dotted,thin] (\bx,0,0) -- (\bx,0,\bz) -- (0,0,\bz);
  \draw[densely dotted,thin] (0,0,\bz) -- (0,\by,\bz) -- (0,\by,0);
  \draw[-{Cone3}] (0,0,0) -- (1,0,0) node[right] {$x$};
  \draw[-{Cone3}] (0,0,0) -- (0,1,0) node[above right] {$y$};
  \draw[-{Cone3}] (0,0,0) -- (0,0,1) node[below right] {$z$};
  \draw[-{Cone3}] (0,0,0) -- (0,0,-1) node[above left] {$-z$};
  \draw[thin] (0,0,0) -- (0,-.9,0);
  \draw[-{Cone3}] (0,0,0) -- (\ax,\ay,\az) node[below left] {source};
  \draw[-{Cone3}] (0,0,0) -- (\bx,\by,\bz) node[above right] {sim};
\end{tikzpicture}

给出了这个数字

在此处输入图片描述

答案1

这种方法允许您分配一个沥青090,其中0表示位于屏幕上,90表示垂直于屏幕。(当然你可以分配91.15566或任何好的数。目前abs代码中的 消除了所有有趣的情况。)

一旦你修复了间距,部件drawing code就会进行一些必要的计算,例如切点的位置。请注意,虽然预定义的箭头提示有一些附加选项,例如openharpoon,但我的提示没有实现它们。我甚至用fill它来摆脱线宽问题。

\documentclass[tikz,border=9]{standalone}
\usepgflibrary{arrows.meta}

\makeatletter

\pgfkeys{
  /pgf/arrow keys/.cd,
  pitch/.code={%
    \pgfmathsetmacro\pgfarrowpitch{#1}
    \pgfmathsetmacro\pgfarrowsinpitch{abs(sin(\pgfarrowpitch))}
    \pgfmathsetmacro\pgfarrowcospitch{abs(cos(\pgfarrowpitch))}
  },
}

\pgfdeclarearrow{
  name = Cone,
  defaults = {       % inherit from Kite
    length     = +3.6pt +5.4,
    width'     = +0pt +0.5,
    line width = +0pt 1 1,
    pitch      = +0, % lie on screen
  },
  cache = false,     % no need cache
  setup code = {},   % so no need setup
  drawing code = {   % but still need math
    % draw the base
    \pgfmathsetmacro\pgfarrowhalfwidth{.5\pgfarrowwidth}
    \pgfmathsetmacro\pgfarrowhalfwidthsin{\pgfarrowhalfwidth*\pgfarrowsinpitch}
    \pgfpathellipse{\pgfpointorigin}{\pgfqpoint{\pgfarrowhalfwidthsin pt}{0pt}}{\pgfqpoint{0pt}{\pgfarrowhalfwidth pt}}
    \pgfusepath{fill}
    % test if the cone part visible
    \pgfmathsetmacro\pgfarrowlengthcos{\pgfarrowlength*\pgfarrowcospitch}
    \pgfmathparse{\pgfarrowlengthcos>\pgfarrowhalfwidthsin}
    \ifnum\pgfmathresult=1
      % it is visible, so draw
      \pgfmathsetmacro\pgfarrowlengthtemp{\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin/\pgfarrowlengthcos}
      \pgfmathsetmacro\pgfarrowwidthtemp{\pgfarrowhalfwidth/\pgfarrowlengthcos*sqrt(\pgfarrowlengthcos*\pgfarrowlengthcos-\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin)}
      \pgfpathmoveto{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{ \pgfarrowwidthtemp pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{-\pgfarrowwidthtemp pt}}
      \pgfpathclose
      \pgfusepath{fill}
    \fi
    \pgfpathmoveto{\pgfpointorigin}
  }
}


\begin{document}

\begin{tikzpicture}[line width=5]
    \draw[-{Cone          }](0,0,0)--(1,0,0);
    \draw[-{Cone          }](0,0,0)--(0,1,0);
    \draw[-{Cone[pitch=60]}](0,0,0)--(0,0,1);
    \path(2,0,0)(0,2,0)(0,0,2);
\end{tikzpicture}

\foreach\theta in{0,10,...,350}{
    \tikz[line width=5]\draw[-{Cone[pitch=\theta]}](-2,0)(2,0)(0,0)--({cos(\theta)},0);
}

\foreach\theta in{0,10,...,350}{
    \tikz[line width=5,opacity=.5]\draw[-{Cone[pitch=\theta]}](-2,0)(2,0)(0,0)--({cos(\theta)},0);
}

\end{document}

更新

我写了三条提示Cone1,,Cone2Cone3

Cone1

它用沥青与上述类似Cone,只是现在检查是否sin(pitch)为阳性。如果是,它假定箭头指向你的眼睛,因此添加一个白点。(同时,cos(pitch)必须为阳性。)

说到点,很难确定正确的尺寸和颜色。目前Cone1读取设置line width并填充一个白色圆圈,其直径就是宽度。这是一个好主意,因为线宽在其他地方没有用到,但如果你真的关心代码的可读性,这也是一个坏主意。

Cone2

本提示接受切线选项,tangent={(1,2,3)}以便它可以计算音高(实际上是它的正弦和余弦)。

问题是,在 Ti 的世界里Z 从来没有人关心过垂直于屏幕的 3D 向量投影。如果我们足够幸运,当前投影到屏幕上是正交类型,这可能是由 指定的tikz-3dplot,那么垂直于屏幕的投影在数学上定义得很好,直到一个符号。(我们无法区分进入屏幕屏幕外将其投影到屏幕上。

不幸的是,在大多数情况下,如果您手动分配x=y=和,z=它将不是正交投影。

在这里,我简单地使用叉积来计算缺失的投影,条件是结果将是正确的如果有人用来tikz-3dplot分配投影。

更准确地说,\tikz@scan@one@point是 Ti 中使用的命令Z 来解析坐标,例如(1,2)(3:4)(A)(5,6,7)。当我写

\tikz@scan@one@point\pgfarrowtangenttosincos#1

并且#1,例如(5,6,7),TiZ 最终将得到

\pgfarrowtangenttosincos{\pgfpointxyz{5}{6}{7}}

然后,根据 的定义\pgfarrowtangenttosincos,PGF 将执行

\pgfpointxyz{5}{6}{7}
\tdplotcrossprod(\pgf@xx,\pgf@yx,\pgf@zx)(\pgf@xy,\pgf@yy,\pgf@zy)

现在

  • (\pgftemp@x,\pgftemp@y,\pgftemp@z)(5,6,7)
  • (\pgf@x,\pgf@y)(5,6,7)是屏幕上的投影。
  • (\tdplotresx,\tdplotresy,\tdplotresz)是叉积的结果。

所以

  • sqrt(\pgf@x*\pgf@x+\pgf@y*\pgf@y)屏幕上的长度
  • (\tdplotresx,\tdplotresy,\tdplotresz)和的内积(\tdplotresx,\tdplotresy,\tdplotresz)是长度屏幕外
  • 以上两个的平方根就是整个向量的长度。

所以

  • 正弦是a/c
  • 余弦是b/c

此后,一切都正常Cone1

Cone3

我做了些改动\pgfpointxyz,让它缓冲两个最近的 3D 坐标。在绘制箭头时,我假设旧的缓冲坐标是终点,而更早的缓冲坐标是起点。因此切线应该是这两个坐标的差。

代码

\documentclass[tikz]{standalone}
\usepgflibrary{arrows.meta}
\usepackage{tikz-3dplot}
\begin{document}


\makeatletter

\pgfkeys{
  /pgf/arrow keys/.cd,
  pitch/.code={%
    \pgfmathsetmacro\pgfarrowpitch{#1}
    \pgfmathsetmacro\pgfarrowcospitch{abs(cos(\pgfarrowpitch))}
    \pgfmathsetmacro\pgfarrowsinpitch{    sin(\pgfarrowpitch)}
  }
}

\pgfdeclarearrow{
  name = Cone1,
  defaults = {       % inherit from Kite
    length     = +3.6pt +5.4,
    width'     = +0pt +0.5,
    line width = +0pt 1 1,
    pitch      = +0, % lie on screen
  },
  cache = false,     % no need cache
  setup code = {},   % so no need setup
  drawing code = {   % but still need math
    % draw the base
    \pgfmathsetmacro\pgfarrowhalfwidth{.5\pgfarrowwidth}
    \pgfmathsetmacro\pgfarrowhalfwidthsin{\pgfarrowhalfwidth*abs(\pgfarrowsinpitch)}
    \pgfpathellipse{\pgfpointorigin}{\pgfqpoint{\pgfarrowhalfwidthsin pt}{0pt}}{\pgfqpoint{0pt}{\pgfarrowhalfwidth pt}}
    \pgfusepath{fill}
    % test if the cone part visible
    \pgfmathsetmacro\pgfarrowlengthcos{\pgfarrowlength*\pgfarrowcospitch}
    \ifdim\pgfarrowlengthcos pt>\pgfarrowhalfwidthsin pt
      % it is visible, so draw
      \pgfmathsetmacro\pgfarrowlengthtemp{\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin/\pgfarrowlengthcos}
      \pgfmathsetmacro\pgfarrowwidthtemp{\pgfarrowhalfwidth/\pgfarrowlengthcos*sqrt(\pgfarrowlengthcos*\pgfarrowlengthcos-\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin)}
      \pgfpathmoveto{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{ \pgfarrowwidthtemp pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{-\pgfarrowwidthtemp pt}}
      \pgfpathclose
      \pgfusepath{fill}
    \else
      % it is invisible, check in pointing your eye
      \ifdim\pgfarrowsinpitch pt>0pt
      \pgfpathcircle{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}{.5\pgfarrowlinewidth}
      \pgfsetcolor{white}
      \pgfusepath{fill}
      \fi
    \fi
    \pgfpathmoveto{\pgfpointorigin}
  }
}
%\begin{tikzpicture}[line width=5]
%   \draw[-{Cone1          }](0,0,0)--(1,0,0);
%   \draw[-{Cone1          }](0,0,0)--(0,1,0);
%   \draw[-{Cone1[pitch=60]}](0,0,0)--(0,0,1);
%   \path(3,0,0)(0,3,0)(0,0,3);
%\end{tikzpicture}
%\foreach\theta in{0,10,...,350}{
%   \tikz[line width=5]\draw[-{Cone1[width'=0 1,pitch=\theta]}](-2,-.5)(2,.5)(0,0)--({cos(\theta)},0);
%}
%\foreach\theta in{0,10,...,350}{
%   \tikz[line width=5,opacity=.5]\draw[-{Cone1[width'=0 1,pitch=\theta]}](-2,-.5)(2,.5)(0,0)--({cos(\theta)},0);
%}








\def\pgfarrowtangenttosincos#1{
    #1
    \tdplotcrossprod(\pgf@xx,\pgf@yx,\pgf@zx)(\pgf@xy,\pgf@yy,\pgf@zy)
    \pgfmathsetmacro\pgfarrowtangentxxyy{\pgf@x*\pgf@x+\pgf@y*\pgf@y}
    \pgfmathsetmacro\pgfarrowtangentxy{sqrt(\pgfarrowtangentxxyy)}
    \pgfmathsetmacro\pgfarrowtangentz{(\pgftemp@x*\tdplotresx+\pgftemp@y*\tdplotresy+\pgftemp@z*\tdplotresz)/72.27*2.54}
    %\message{^^J^^J(\tdplotresx,\tdplotresy,\tdplotresz)(\pgfarrowtangentxy,\pgfarrowtangentz)}\show\\
    \pgfmathsetmacro\pgfarrowtangentxyz{sqrt(\pgfarrowtangentxxyy+\pgfarrowtangentz*\pgfarrowtangentz)}
    \pgfmathsetmacro\pgfarrowcospitch{\pgfarrowtangentxy/\pgfarrowtangentxyz}
    \pgfmathsetmacro\pgfarrowsinpitch{\pgfarrowtangentz/\pgfarrowtangentxyz}
}
\pgfkeys{
  /pgf/arrow keys/.cd,
  tangent/.code={%
    \tikz@scan@one@point\pgfarrowtangenttosincos#1
  }
}
\pgfdeclarearrow{
  name = Cone2,
  defaults = {             % inherit from Kite
    length     = +3.6pt +5.4,
    width'     = +0pt +0.5,
    line width = +0pt 1 1,
    tangent    = {(1,0,0)} % lie on x-axis
  },
  cache = false,           % no need cache
  setup code = {},         % so no need setup
  drawing code = {         % but still need math
    % draw the base
    \pgfmathsetmacro\pgfarrowhalfwidth{.5\pgfarrowwidth}
    \pgfmathsetmacro\pgfarrowhalfwidthsin{\pgfarrowhalfwidth*abs(\pgfarrowsinpitch)}
    \pgfpathellipse{\pgfpointorigin}{\pgfqpoint{\pgfarrowhalfwidthsin pt}{0pt}}{\pgfqpoint{0pt}{\pgfarrowhalfwidth pt}}
    \pgfusepath{fill}
    % test if the cone part visible
    \pgfmathsetmacro\pgfarrowlengthcos{\pgfarrowlength*\pgfarrowcospitch}
    \ifdim\pgfarrowlengthcos pt>\pgfarrowhalfwidthsin pt
      % it is visible, so draw
      \pgfmathsetmacro\pgfarrowlengthtemp{\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin/\pgfarrowlengthcos}
      \pgfmathsetmacro\pgfarrowwidthtemp{\pgfarrowhalfwidth/\pgfarrowlengthcos*sqrt(\pgfarrowlengthcos*\pgfarrowlengthcos-\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin)}
      \pgfpathmoveto{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{ \pgfarrowwidthtemp pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{-\pgfarrowwidthtemp pt}}
      \pgfpathclose
      \pgfusepath{fill}
    \else
      % it is invisible, check in pointing your eye
      \ifdim\pgfarrowsinpitch pt>0pt
      \pgfpathcircle{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}{.5\pgfarrowlinewidth}
      \pgfsetcolor{white}
      \pgfusepath{fill}
      \fi
    \fi
    \pgfpathmoveto{\pgfpointorigin}
  }
}
\tdplotsetmaincoords{70}{110}
\begin{tikzpicture}[line width=5,tdplot_main_coords]
    \draw[-{Cone2[tangent={(1,0,0)}]}](0,0,0)--(1,0,0)node[cyan]{X};
    \draw[-{Cone2[tangent={(0,1,0)}]}](0,0,0)--(0,1,0)node[cyan]{Y};
    \draw[-{Cone2[tangent={(0,0,1)}]}](0,0,0)--(0,0,1)node[cyan]{Z};
    \path(-2cm,-2cm)(2cm,2cm);
\end{tikzpicture}

\foreach\theta in{0,10,...,350}{
    \tdplotsetrotatedcoords{\theta}{30}{30}
    \tikz[line width=5,line cap=round,tdplot_rotated_coords]{
        \draw[-{Cone2[tangent={(1,0,0)}]}](0,0,0)--(1,0,0)node[cyan]{X};
        \draw[-{Cone2[tangent={(0,1,0)}]}](0,0,0)--(0,1,0)node[cyan]{Y};
        \draw[-{Cone2[tangent={(0,0,1)}]}](0,0,0)--(0,0,1)node[cyan]{Z};
        \path(-2cm,-2cm)(2cm,2cm);
    }
}










\def\pgfpointxyz#1#2#3{%
  \pgfmathparse{#1}%
  \let\pgftemp@x=\pgfmathresult%
  \pgfmathparse{#2}%
  \let\pgftemp@y=\pgfmathresult%
  \pgfmathparse{#3}%
  \let\pgftemp@z=\pgfmathresult%
  \pgf@x=\pgftemp@x\pgf@xx%
  \advance\pgf@x by \pgftemp@y\pgf@yx%
  \advance\pgf@x by \pgftemp@z\pgf@zx%
  \pgf@y=\pgftemp@x\pgf@xy%
  \advance\pgf@y by \pgftemp@y\pgf@yy%
  \advance\pgf@y by \pgftemp@z\pgf@zy%
  % ↑↑↑old definition↑↑↑ ↓↓↓new code↓↓↓
  \global\let\pgfolderpointx\pgfoldpointx
  \global\let\pgfolderpointy\pgfoldpointy
  \global\let\pgfolderpointz\pgfoldpointz
  \global\let\pgfoldpointx\pgftemp@x
  \global\let\pgfoldpointy\pgftemp@y
  \global\let\pgfoldpointz\pgftemp@z
}


\pgfdeclarearrow{
  name = Cone3,
  defaults = {             % inherit from Kite
    length     = +3.6pt +5.4,
    width'     = +0pt +0.5,
    line width = +0pt 1 1,
    tangent    = {(1,0,0)} % lie on x-axis
  },
  cache = false,           % no need cache
  setup code = {},         % so no need setup
  drawing code = {         % but still need math
    % calculate the tangent
    \pgfkeys{pgf/arrow keys/tangent={(\pgfoldpointx-\pgfolderpointx,\pgfoldpointy-\pgfolderpointy,\pgfoldpointz-\pgfolderpointz)}}
    % draw the base
    \pgfmathsetmacro\pgfarrowhalfwidth{.5\pgfarrowwidth}
    \pgfmathsetmacro\pgfarrowhalfwidthsin{\pgfarrowhalfwidth*abs(\pgfarrowsinpitch)}
    \pgfpathellipse{\pgfpointorigin}{\pgfqpoint{\pgfarrowhalfwidthsin pt}{0pt}}{\pgfqpoint{0pt}{\pgfarrowhalfwidth pt}}
    \pgfusepath{fill}
    % test if the cone part visible
    \pgfmathsetmacro\pgfarrowlengthcos{\pgfarrowlength*\pgfarrowcospitch}
    \ifdim\pgfarrowlengthcos pt>\pgfarrowhalfwidthsin pt
      % it is visible, so draw
      \pgfmathsetmacro\pgfarrowlengthtemp{\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin/\pgfarrowlengthcos}
      \pgfmathsetmacro\pgfarrowwidthtemp{\pgfarrowhalfwidth/\pgfarrowlengthcos*sqrt(\pgfarrowlengthcos*\pgfarrowlengthcos-\pgfarrowhalfwidthsin*\pgfarrowhalfwidthsin)}
      \pgfpathmoveto{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{ \pgfarrowwidthtemp pt}}
      \pgfpathlineto{\pgfqpoint{\pgfarrowlengthtemp pt}{-\pgfarrowwidthtemp pt}}
      \pgfpathclose
      \pgfusepath{fill}
    \else
      % it is invisible, check in pointing your eye
      \ifdim\pgfarrowsinpitch pt>0pt
      \pgfpathcircle{\pgfqpoint{\pgfarrowlengthcos pt}{0pt}}{.5\pgfarrowlinewidth}
      \pgfsetcolor{white}
      \pgfusepath{fill}
      \fi
    \fi
    \pgfpathmoveto{\pgfpointorigin}
  }
}
\tdplotsetmaincoords{70}{110}
\begin{tikzpicture}[line width=5,tdplot_main_coords]
    \draw[-{Cone2[tangent={(1,0,0)}]}](0,0,0)--(1,0,0)node[cyan]{X};
    \draw[-{Cone2[tangent={(0,1,0)}]}](0,0,0)--(0,1,0)node[cyan]{Y};
    \draw[-{Cone2[tangent={(0,0,1)}]}](0,0,0)--(0,0,1)node[cyan]{Z};
    \path(-2cm,-2cm)(2cm,2cm);
\end{tikzpicture}

\foreach\theta in{0,5,...,355}{
    \tdplotsetrotatedcoords{\theta}{2*\theta}{3*\theta}
    \tikz[line width=5,line cap=round,tdplot_rotated_coords]{
        \draw[-Cone3](0,0,0)--(1,0,0)node[cyan]{X};
        \draw[-Cone3](0,0,0)--(0,1,0)node[cyan]{Y};
        \draw[-Cone3](0,0,0)--(0,0,1)node[cyan]{Z};
        \path(-2cm,-2cm)(2cm,2cm);
    }
}




\end{document}

答案2

这个如何?

在此处输入图片描述

\documentclass[margin=10pt]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[scale=3]
\def\opaque{0.035}    % rendering opacity 
\def\prop{1.3}        % variable of rendering opacity
\def\R{2} %           % cone slant height
\def\theta{21}        % 2*\theta is the angle of expanded by the tip of the cone
\def\range{100}       % number of interaction for smooth rending effect
\def\ratio{0.4}       % ellipse b/a for cone lower edge 
\def\aratio{0.35}     % a_rod / a_cone  
\def\height{0.8}      % rod height 
\def\fraction{0.375}  % ellipse b/a for rod edge 
\def\angle{12}        % angle extended by rod edge
\def\total{60}        % number of interaction for smooth rending effect
\def\conecolor{red!\range!black!40!red}   % cone color 

\foreach \i in {0,...,\range}
{
    \fill[\conecolor, opacity={\opaque+\prop*\opaque*(\range-2*\i)/\range}] (0, {\R*cos(\theta)}) -- ({\R*sin(\theta)*cos(270+90*\i/\range)},{\ratio*\R*sin(\theta)*sin(270+90*\i/\range)})  arc({270+90*\i/\range}:360: {\R*sin(\theta)}  and {\ratio*\R*sin(\theta)} ) -- cycle;
    \fill[\conecolor, opacity={\opaque+\prop*\opaque*(\range-\i)/\range}] (0, {\R*cos(\theta)}) -- ({\R*sin(\theta)*cos(270-90*\i/\range)},{\ratio*\R*sin(\theta)*sin(270-90*\i/\range)})  arc({270-90*\i/\range}:180: {\R*sin(\theta)}  and {\ratio*\R*sin(\theta)} ) -- cycle;
}
\definecolor{conered}{RGB}{255,114,114}
\definecolor{conegreen}{RGB}{37,146,37}
\definecolor{coneblue}{RGB}{107,107,236}

\fill[conered] (-0.7167,0) arc (180:360: 0.7167 and 0.2867)  arc (0:180: 0.7167 and 0.2867) -- cycle ;

\pgfmathparse{\R*sin(\theta)*\aratio}

\fill[conered] (-0.251, -{sqrt(1-0.251*0.251/(0.7167*0.7167) )*0.2867}) arc ({360-acos(-0.251/0.7167) )}:{360-acos(0.251/0.7167 )}: 0.7167 and 0.2867 ) -- (0.251,-\height) arc (360:180:0.251 and 0.0941) --cycle ;

\foreach \i  in {0,...,\total}
{
    \fill[\conecolor, opacity={2*\opaque+\prop*\opaque*(\total-1*\i)/\total}] ({\pgfmathresult*\i/\total}, {\pgfmathresult*\ratio*sqrt(1-\i/\total*\i/\total) } )  arc ( {acos(\i/\total)}:0: {\R*sin(\theta)*\aratio} and {\R*sin(\theta)*\aratio*\ratio} ) -- ++(0,-\height) arc (360: {360-acos(\i/\total)}: {\R*sin(\theta)*\aratio} and {\R*sin(\theta)*\aratio*\ratio} ) -- cycle;
    \fill[\conecolor, opacity={2*\opaque+\prop*\opaque*(\total-1*\i)/\total}] ({-\R*sin(\theta)*\aratio*\i/\total}, {\R*sin(\theta)*\aratio*\ratio*sqrt(1-\i/\total*\i/\total) } )  arc ( {acos(-\i/\total)}:180: {\R*sin(\theta)*\aratio} and {\R*sin(\theta)*\aratio*\ratio} ) -- ++(0,-\height) arc (180: {360-acos(-\i/\total)}: {\R*sin(\theta)*\aratio} and {\R*sin(\theta)*\aratio*\ratio} ) -- cycle;
}

\draw[thick, conered, yshift=-0.8cm] (-0.251,0.8) -- (-0.251,0) arc (180:360:0.251 and 0.0941) -- (0.251,0.8);
\end{tikzpicture}

\end{document}

相关内容