如何在 3D 图形中绘制覆盖一组点的凸形?

如何在 3D 图形中绘制覆盖一组点的凸形?

考虑三维散点图中的点,例如以下:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{datatool}
\DTLloaddb[noheader=false]{coordinates}{data.csv}
\pgfplotsset{compat=1.12}

\usepackage{filecontents}
\begin{filecontents*}{data.csv}
xc,yc,xer,yer,phi
1,4,0.04,0.02,0.5
2,3,0.87,0.24,1
3,5,0.02,0.3,2.35
4,1,0.4,0.9,2.5
5,3,0.2,0.1,0.2
2.5,3,1.2,0.5,0.2
3,2,1,0.25,2.3
\end{filecontents*}

\begin{document}

\begin{tikzpicture}
\def\Xmin{0}
\def\Ymin{-0.5}
\begin{axis}[
  xmin=\Xmin,
  ymin=\Ymin,
]
\addplot table [x=xc, y=yc, col sep=comma, only marks, mark=0] {data.csv};
\pgfplotsextra{\DTLforeach*{coordinates}{\x=xc, \y=yc,\xr=xer,\yr=yer,\an=phi}{
  \filldraw[blue,fill opacity=0.2] 
    (axis cs:\x,\y) ellipse [x radius=\xr,y radius=\yr,rotate around={deg(\an):(\Xmin,\Ymin)}];
  }
}
\end{axis}
\end{tikzpicture}

\end{document}

我的问题是如何围绕该图中指定的一组点绘制凸 3d 形状(非标准形状)?

答案1

有一个长时间的讨论关于绘制凸包,我选择了这个答案要得到

\documentclass{article}
\usepackage{pgfplots}
\usepackage{datatool}
\DTLloaddb[noheader=false]{coordinates}{data.csv}
\pgfplotsset{compat=1.12}
% pgfmanual p. 1087
\pgfdeclareradialshading{ellipseshading}{\pgfpoint{-10bp}{10bp}}
 {color(0bp)=(cyan!15!white); color(9bp)=(cyan!75!white);
 color(18bp)=(cyan!70!black); color(25bp)=(cyan!50!black); color(50bp)=(black)}

\pgfdeclareplotmark{elli}{\pgfpathellipse{\pgfpointorigin}{\pgfpoint{2mm}{0cm}}{\pgfpoint{0cm}{3.5mm}}
  \pgfshadepath{ellipseshading}{0}
  \pgfusepath{}}
\makeatletter
\pgfkeyssetvalue{/tikz/convex hull}{\let\tikz@plot@handler=\pgfplothandlerconvexhull}
\pgfdeclareplothandler{\pgfplothandlerconvexhull}{}{
  start = {\pgf@plot@mark@count = 1},
  point = {\pgfcoordinate{convex hull-\the\pgf@plot@mark@count}{##1}\global\advance\pgf@plot@mark@count by1\relax},
  end   = {% Find the top point
            \pgfmathtruncatemacro\pgf@ch@total{\the\pgf@plot@mark@count-1}%
            \pgf@plot@mark@count = 0\pgfmathtruncatemacro\xe{int(\pgf@ch@total-1)}%
            \foreach\x in{1,...,\xe}{%
              \def\pgf@ch@invalid@flag{0}\pgfmathtruncatemacro\xx{int(\x+1)}%
              \foreach\y in{\xx,...,\pgf@ch@total}{%
                \pgfmathanglebetweenpoints{\pgfpointanchor{convex hull-\x}{center}}%
                     {\pgfpointanchor{convex hull-\y}{center}}%
                %\typeout{current test \x - \y : angle \pgfmathresult}
                \ifdim 180pt >\pgfmathresult pt\relax\xdef\pgf@ch@invalid@flag{1}\breakforeach\fi%
              }%
              \ifnum\pgf@ch@invalid@flag<1\relax\xdef\pgf@ch@first@{\x}\breakforeach\else%
              \xdef\pgf@ch@first@{\pgf@ch@total}\fi%
            }% Found. Now look at upperright then switch to that and rotate...loop
            \edef\pgf@ch@current@{\pgf@ch@first@}\def\pgf@ch@current@angle{0}%
            \edef\pgf@ch@collected{\pgf@ch@first@}\def\pgf@ch@temp@max@{0}%
            \foreach\x in {1,...,\pgf@ch@total}{
                \pgftransformshift{\pgfpointdiff{\pgfpointorigin}%
                              {\pgfpointanchor{convex hull-\pgf@ch@current@}{center}}}%
                \pgftransformrotate{\pgf@ch@current@angle-360}%
                \pgfmathloop%
                    \ifnum\pgfmathcounter=\pgf@ch@current@\relax\else%
                        \pgfmathanglebetweenpoints{\pgfpointanchor{convex hull-\pgf@ch@current@}{center}}%
                                                  {\pgfpointanchor{convex hull-\pgfmathcounter}{center}}%
                        \edef\pgf@ch@current@angle{\pgfmathresult}%
                        \ifdim\pgf@ch@current@angle pt>\pgf@ch@temp@max@ pt\relax%
                            \edef\pgf@ch@temp@max@{\pgf@ch@current@angle}%
                            \edef\pgf@ch@temp@current@{\pgfmathcounter}%
                            %\typeout{new max for \pgf@ch@current@ with \the\c@pgf@countd: angle \pgf@ch@current@angle}
                        \fi%
                    \fi%
                \ifnum\pgfmathcounter<\pgf@ch@total\repeatpgfmathloop%
                \xdef\pgf@ch@current@angle{\pgf@ch@temp@max@}%
                \xdef\pgf@ch@current@{\pgf@ch@temp@current@}%
                \expandafter\xdef\expandafter\pgf@ch@collected\expandafter{\pgf@ch@collected,\pgf@ch@current@}%
                \ifnum\pgf@ch@current@=\pgf@ch@first@\relax\breakforeach\fi%
                %\typeout{\pgf@ch@collected}
            }%
            \foreach\x[count=\xi] in\pgf@ch@collected{%
            \ifnum\xi=1\relax\pgfpathmoveto{\pgfpointanchor{convex hull-\x}{center}}\else%
            \pgfpathlineto{\pgfpointanchor{convex hull-\x}{center}}\fi%
            }\pgfpathclose%
   }
}
\makeatother
\usepackage{filecontents}
\begin{filecontents*}{data.csv}
xc,yc,xer,yer,phi
1,4,0.04,0.02,0.5
2,3,0.87,0.24,1
3,5,0.02,0.3,2.35
4,1,0.4,0.9,2.5
5,3,0.2,0.1,0.2
2.5,3,1.2,0.5,0.2
3,2,1,0.25,2.3
\end{filecontents*}

\begin{document}

\begin{tikzpicture}
\def\Xmin{0}
\def\Ymin{-0.5}
\begin{axis}[
  xmin=\Xmin,
  ymin=\Ymin,
]
\addplot[only marks, mark=*] table [x=xc, y=yc, col sep=comma] {data.csv};
%\addplot[only marks, mark=elli,opacity=0.7] table [x=xc, y=yc, col sep=comma] {data.csv};

\addplot[/tikz/convex hull]  table [x=xc, y=yc, col sep=comma] {data.csv};
% \pgfplotsextra{\DTLforeach*{coordinates}{\x=xc, \y=yc,\xr=xer,\yr=yer,\an=phi}{
%   \filldraw[blue,fill opacity=0.2] 
%     (axis cs:\x,\y) ellipse [x radius=\xr,y radius=\yr,rotate around={deg(\an):(\Xmin,\Ymin)}];
%   }
% }
\end{axis}
\end{tikzpicture}

\end{document}

在此处输入图片描述

我不确定这是你想要的。(而且你的第二个方法\addplot没有奏效。我添加了一个替代方案,我声明了一个情节标记来生成一些我认为可能是你想要的东西。)

相关内容