7

I am trying to draw a cylinder inside a sphere like this picture enter image description here

I tried:

\documentclass[12pt,border=3mm]{standalone}
\usepackage{fouriernc}
\usepackage{tikz}
\usepackage{tkz-euclide}
\usetkzobj{all}
\usepackage{tikz-3dplot}
\usetikzlibrary{calc,backgrounds}
\begin{document}
\tdplotsetmaincoords{70}{110}
\def\r{{2*sqrt(3)}}
\def\d{-60}
\begin{tikzpicture}
[scale=1,tdplot_main_coords]
\path
coordinate (O) at (0,0,0)
coordinate (I) at  (0,0,2)
coordinate (A') at  (0,\r,4)
coordinate (A) at  (0,\r,0);
\coordinate (B) at ($(O) + (\d:{2*sqrt(3)} and \r)$);
\coordinate (B') at ($(B)+(0,0,4)$);
\coordinate (O') at ($(O)+(0,0,4)$);
\draw[dashed] (A)--(A') (B) --(B') (O)--(O') (O)--(A) (I) --(A);
\foreach \v/\position in {I/left,O/below,O'/above,A/below,B/below,A'/left,B'/left} {
    \draw[draw =black, fill=black] (\v) circle (1.2pt) node [\position=0.2mm] {$\v$};
}
\begin{scope}[tdplot_screen_coords, on background layer]
\pgfmathsetmacro{\R}{4}%
%\pgfmathsetmacro{\r}{{2*sqrt(3)}}%
\fill[ball color=orange!70, opacity=1.0] (I) circle (\R);
\end{scope}
\tkzMarkRightAngle[size = 0.3](I,O,A);
\draw [thick] (B) arc (\d:90:\r);
\draw [thick, dashed] (A) arc (90:310:\r);
\draw [thick] (B') arc (\d:90:\r);
\draw [thick, dashed] (A') arc (90:310:\r);
\end{tikzpicture}
\end{document}

I got enter image description here

The cylinder look very bad. How can I repair it?

1 Answers1

5

Points (A) (B) (A') and (B') are not the edges of the cylinder, but rather the points where the visible edge of the sphere (circle) and the visible edge of of the cylinder (ellipse) intersect, which depend on the viewing angles.
Points (C) and (D) represent the visible right and left edges.

math

\documentclass[12pt,border=3mm]{standalone}
\usepackage{fouriernc}
\usepackage{tikz}
\usepackage{tkz-euclide}
\usetkzobj{all}
\usepackage{tikz-3dplot}
\usetikzlibrary{calc,backgrounds}
\begin{document}
\def\myangle{70}%
\tdplotsetmaincoords{\myangle}{0}%

\begin{tikzpicture}[scale=1,tdplot_main_coords]
\pgfmathsetmacro{\r}{2*sqrt(3)}% sphere radius=4, cylendar height=4
\path% common coordinates
  (0,0,-2) coordinate (O)
  (0,0,0) coordinate (I)
  (0,0,2) coordinate (O')
  (O) ++(0:\r) coordinate (C)% right edge
  (O) ++(180:\r) coordinate (D);% left edge
\draw[dashed,thick] (C)-- ++(0,0,4) (D)-- ++(0,0,4);
\draw[dashed] (O)--(O');
\begin{scope}[tdplot_screen_coords, on background layer]
      \fill[ball color=orange!70, opacity=1.0] (I) circle (4);
\end{scope}

\pgfmathsetmacro{\mynumer}{2*cos(\myangle)}
\pgfmathsetmacro{\mydenom}{\r*sin(\myangle)}
\pgfmathsetmacro{\quadrant}{ifthenelse(abs(\mynumer)<abs(\mydenom), 0,
  ifthenelse(\mynumer>0, 1, 2))}% 0=side, 1=top, 2=bottom

\ifcase\quadrant
  \pgfmathsetmacro{\intercept}{asin(\mynumer/\mydenom)}
  \path
    (O) ++(-\intercept:\r) coordinate (A)
    (O) ++(-180+\intercept:\r) coordinate (B)
    (O') ++(\intercept:\r) coordinate (A')
    (O') ++(180-\intercept:\r) coordinate (B');
  \draw [thick] (B) arc (-180+\intercept:-\intercept:\r);
  \draw [thick, dashed] (A) arc (-\intercept:180+\intercept:\r);
  \draw [thick] (B') arc (-180-\intercept:\intercept:\r);
  \draw [thick, dashed] (A') arc (\intercept:180-\intercept:\r);

  \foreach \v/\position in {I/left,O/below,O'/above,A/below,B/below,A'/left,B'/left} {
    \draw[draw =black, fill=black] (\v) circle (1.2pt) node [\position=0.2mm] {$\v$};
  }
\or% top
  \path
    (C) coordinate (A)
    (D) coordinate (B)
    (A) ++(0,0,4) coordinate (A')
    (B) ++((0,0,4) coordinate (B');
  \draw [thick] (O') circle (\r);
  \draw [thick, dashed] (O) circle (\r);

  \foreach \v/\position in {I/left,O/below,O'/above,A/below,B/below,A'/left,B'/left} {
    \draw[draw =black, fill=black] (\v) circle (1.2pt) node [\position=0.2mm] {$\v$};
  }
\or% bottom
  \path
    (C) coordinate (A)
    (D) coordinate (B)
    (A) ++(0,0,4) coordinate (A')
    (B) ++((0,0,4) coordinate (B');
  \draw [thick,dashed] (O') circle (\r);
  \draw [thick] (O) circle (\r);

  \foreach \v/\position in {I/left,O/below,O'/above,A/below,B/below,A'/left,B'/left} {
    \draw[draw =black, fill=black] (\v) circle (1.2pt) node [\position=0.2mm] {$\v$};
  }
\fi

\draw[dashed] (O)--(A) (I) --(A);
\tkzMarkRightAngle[size = 0.3](I,O,A);
\end{tikzpicture}
\end{document}

demo

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • Is there a code true for every cylinder? – minhthien_2016 Nov 15 '17 at 15:44
  • Yes and no. You need one solution for small \phi and another for large \phi. Then you need to calculate \theta using pgfmath (I just used a calculator). – John Kormylo Nov 15 '17 at 15:48
  • I shall try to write a general code. When I see difficult, I need your help. Can you help me? – minhthien_2016 Nov 15 '17 at 16:12
  • The tricky bit is the test for h \cot\phi/r_x. pgfmath has a ifthenelse command, but it basically only affects \pgfmathresult. LaTeX has \ifdim\len<1pt\relax ... \else ... \fi construction but you will need to append pt to the number. – John Kormylo Nov 15 '17 at 16:27
  • New thought: use \pgfmathparse or \pgfmathsetmacro to assign 0,1,2 and possibly 3 then use \ifcases\pgfmathresult\relax ... \else ... \else ... \fi to implement the images. BTW, \relax means "Stop looking for more digits. This number is done." – John Kormylo Nov 16 '17 at 13:55
  • I am sory. I am too busy now. I have not enought time to try. – minhthien_2016 Nov 24 '17 at 08:42
  • The revised solution can handle can handle any angle. Except \tkzMarkRightAngle cannot handle 0 degrees (divide by zero). – John Kormylo Nov 24 '17 at 16:56
  • I tried to change your code with some replaces as `\def\R{4}% \def\h{4}% \tdplotsetmaincoords{\myangle}{0}%

    \begin{tikzpicture}[scale=1,tdplot_main_coords] \pgfmathsetmacro{\r}{sqrt(\R^2-\h^2/4)}% sphere radius=4, cylendar height=4 \path% common coordinates (0,0,-\R/2) coordinate (O) (0,0,0) coordinate (I) (0,0,\R/2) coordinate (O') (O) ++(0:\r) coordinate (C)% right edge (O) ++(180:\r) coordinate (D);% left edge \draw[dashed,thick] (C)-- ++(0,0,\h) (D)-- ++(0,0,\h);It works. Can you write a general code when I chooce everyRandh`?

    – minhthien_2016 Nov 25 '17 at 03:40
  • BTW, \R\R is MUCH faster than \R^2 = exp(2log(\R)) – John Kormylo Nov 25 '17 at 14:58
  • @ John Kormylo, When I change \def\myangle{50}, It seems wrong. – minhthien_2016 Nov 11 '19 at 14:43
  • Looks fine to me. Note that 0 is the north pole and 90 is the equator. – John Kormylo Nov 11 '19 at 14:56