13

I am trying to put two polar planes/axes around an object (here a heart in Fig. 2) by TikZ/... translations and rotations for 3D phenomena. I think the problem is to Translate and rotate the second polar grid around the object (heart) for 3D phenomena.

I can do one polar grid as described in the thread Creating a Polar Grid with Tikz. You can use the heart in Figure 2 directly which needs a polar system around it. I can rotate objects (here the second coordinate system), described in the thread Translate and rotate an object in TikZ (2D). The 3D translation can be done as described in the thread answer Tikz:: shift and rotate in 3d? The 3D rotation seems to be without a solution but I am not sure if it is the only limiting factor here.

Fig. 1 Target object, Fig. 2 Heart in Mathematica (here code), Fig. 3 Output of the code in 2D plane

enter image description here enter image description here enter image description here

Simplified 2D polar grid with concentric circles

# https://tex.stackexchange.com/a/169639/13173
\documentclass{article}    
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[>=latex]

% Draw the lines at multiples of pi/12
\foreach \ang in {0,...,31} {
  \draw [lightgray] (0,0) -- (\ang * 180 / 16:4);
}    
% Concentric circles and radius labels
\foreach \s in {0, 1, 2, 3} {
  \draw [lightgray] (0,0) circle (\s + 0.5);
  \draw (0,0) circle (\s);
  \node [fill=white] at (\s, 0) [below] {\scriptsize $\s$};
}
% Add the labels at multiples of pi/4
\foreach \ang/\lab/\dir in {
  0/0/right,
  1/{\pi/4}/{above right},
  2/{\pi/2}/above,
  3/{3\pi/4}/{above left},
  4/{\pi}/left,
  5/{5\pi/4}/{below left},
  7/{7\pi/4}/{below right},
  6/{3\pi/2}/below} {
  \draw (0,0) -- (\ang * 180 / 4:4.1);
  \node [fill=white] at (\ang * 180 / 4:4.2) [\dir] {\scriptsize $\lab$};
}
% The double-lined circle around the whole diagram
\draw [style=double] (0,0) circle (4);

\end{tikzpicture} 
\end{document}

Expected output: heart in polar grid system as Fig. 1 by using Fig. 2 + without any decorations

Simplified proposal in 2D [deprecated]

Pseudocode motivated by the thread answer Smileys in LaTeX

  • any approach forward is welcome, 2D is also ok. Anything visualising the case better is welcome.
    1. two balls (here, one for polar coordinates) and second for the heart (assume heart first ball)
    2. +put heart inside the bigger ball
    3. +apply surfaces similarly as in the previous thread: Inkscape used to export the surface characteristics in Tikz directly

Conclusion: [tikz-3D has nothing to do with inkscape]

Sources

  1. Wolfram Research, Inc., Mathematica, Version 11.1, Champaign, IL (2017). Fig. 2.

TeXLive: 2017
OS: Debian 8.7

  • 3
    With tikz3d you can add a scope with a different (absolute) orientation. You can do the same with standard tikz using \pgfsetxvec etc. (page 977) but you have to do your own trigonometry. – John Kormylo Dec 22 '16 at 23:04
  • 3
    Wouldn't it be easier to use a drawing tool which supports 3D rather than faking it in 2D? – cfr Dec 23 '16 at 3:02
  • I also needed to show my mechanical arm simulation in Solidworks: youtube.com/watch?v=crJXUlzJ918 – LCarvalho Feb 22 '18 at 9:58
11

3D is really hard to achieve properly, I cheated too. I'm looking through Section 96 (pg. 978) of the manual that describes 3d polar systems. It has a latitude/longitude system defined, but the equator lies in the page -.-

Until I figure out how to rotate the globe as given there, my solution:

\documentclass[tikz,border=20pt]{standalone}
\usetikzlibrary{decorations.text}
\begin{document}


\begin{tikzpicture}
%%Change the angle with yscale
%%in the back
\begin{scope}[yscale=.4]
\foreach \x in {0,20, 60, 100, 140}
    \draw (\x:2) -- (\x:5.2) (\x:6) node {label \x};
\end{scope}

%%actual image (use transparency for proper display
\draw (0,0) node (heart) {\includegraphics[width=5cm]{Zy6t1}};

%front
\begin{scope}[yscale=.4]
\foreach \x in {0, 10,...,360}
    \draw (\x:4.8) -- (\x:5);
\draw[double] (0,0) circle (5);
\foreach \x in {180,220, 260, 300, 340}
    \draw (\x:2) -- (\x:5.2) (\x:6) node {label \x};
\end{scope}

%arcs around the top
\draw[ultra thick, gray!50] (30:5.3) -- (30:5.5) arc (30:60:5.5);
\path decorate [decoration={text along path, text={right top label },text align= {align=center},reverse path,text color=gray!50}] {(30:5.7) arc (30:60:5.7)};

\draw[ultra thick, gray!50] (120:5.5) arc (120:150:5.5) -- (150:5.3);
\path decorate [decoration={text along path, text={left top label },text align= {align=center},reverse path,text color=gray!50}] {(120:5.7) arc (120:150:5.7)};

\draw[ultra thick, gray] (60:5.3) -- (60:5.5) arc (60:120:5.5) -- (120:5.3);
\path decorate [decoration={text along path, text={Middle top label },text align= {align=center},reverse path, text color=gray}] {(60:5.7) arc (60:120:5.7)};

\fill[blue!60] (250:5.5) -- (250:3) -- (251:5.5) --cycle node[below,color=gray] {Bottom label 1};
\fill[blue!60] (280:5.5) -- (280:3) -- (281:5.5) --cycle node[below,color=gray] {Bottom label 2};
\end{tikzpicture}

enter image description here

(I have not added transparency)

The labels in the are "rotated" with y-scale. Those behind the image have to sit in the background, which you can do either with layer=background (or similar, didn't look up the command) or the lazy way by splitting the ring. I have tried to copy the elements of the image you provide with different methods as to give you starters on how to continue.

I don't want no bounty until I figure out the proper 3d system. In general however, it is sufficient to fake 3d with the methods provided in both answers. In the case provided here, this even more true as you only have two planes, the vertical and the horizontal one. If you had a globe where you wanted to label cities, true 3d would be much appropriate. Back in a few with progress on a proper system…

I have used up the time allocated, I need to focus on my work and not draw hearts in LaTeX. Sadly, the basic pgf layer is beyond my abilities. Instead, I have another fake variant for you, in the form of the xyz angle canvas system. The ring is split again for proper foreground/background separation (this time with backgrounds to keep the logical grouping).

\documentclass[tikz,border=20pt]{standalone}
\usetikzlibrary{backgrounds}
\begin{tikzpicture}[label/.style={font=\footnotesize,gray}]
%Bottom back
\foreach \a in {0,30,...,180}
    {
    \path (0,-3,0) {+ (xyz polar cs: angle = \a, x radius =5, y radius = 2) node (T\a){}};
    \path (0,-1,0) {+ (xyz polar cs: angle = \a, x radius =2, y radius = 0.8) node (B\a){}};
    \draw[on background layer] (T\a) node[label] {T\a} -- (B\a);}
%bottom front
\foreach \a in {210,240,...,330}
    {
    \path (0,-3,0) {+ (xyz polar cs: angle = \a, x radius =5, y radius = 2) node (T\a){}};
    \path (0,-1,0) {+ (xyz polar cs: angle = \a, x radius =2, y radius = 0.8) node (B\a){}};
    \draw (T\a) node[label] {T\a} -- (B\a);}
%heart image    
\draw (0,0) node (heart) {\includegraphics[width=5cm]{QwMQn}};

%top back
\foreach \a in {0,30,...,180}
    {
    \path (0,3,0) {+ (xyz polar cs: angle = \a, x radius =5, y radius = 2) node (T\a){}};
    \path (0,1,0) {+ (xyz polar cs: angle = \a, x radius =2, y radius = 0.8) node (B\a){}};
    \draw (T\a) node[label] {T\a} -- (B\a);}

%top front
\foreach \a in {210,240,...,330}
    {
    \path (0,3,0) {+ (xyz polar cs: angle = \a, x radius =5, y radius = 2) node (T\a){}};
    \path (0,1,0) {+ (xyz polar cs: angle = \a, x radius =2, y radius = 0.8) node (B\a){}};
    \draw (T\a) node[label] {T\a} -- (B\a);}
\end{tikzpicture}
\end{document}

This emulates a cylindrical system perpendicular to the paper with different heights for the top and bottom end of the label pins. Angles (around height) can be changed within the \foreach, height of top and bottom layer in (0,3,0) in the paths. The angle relative to the paper is related to the ratio between x radius and y radius. Essentially it draws ellipses that are shifted vertically. Coordinates are connected with the \draw command.

enter image description here

Depending on my workload, I may stare at the rotate 3d solution for some time. Essentially one would have to handle the height, angle and distortion in one group.


(Put into new answer)

  • 1
    What do you mean by full source? You mean a link to the manual? Can be found here: ctan.org/pkg/pgf – Huang_d Jun 18 '17 at 10:02
  • Yes, the link is enough, please add it to the body. - - Here direct link to the page mirror.datacenter.by/pub/mirrors/CTAN/graphics/pgf/base/doc/…, I think. – Léo Léopold Hertz 준영 Jun 18 '17 at 10:02
  • 1
    @LéoLéopoldHertz준영 Why? It is just the manual. – cfr Jun 18 '17 at 21:53
  • Did you look at tikz-3dplot? It can do lots of the calculations required for 3d for you. (But not sure whether it would help you here or not.) – cfr Jun 18 '17 at 22:09
  • @cfr … well… no… I guess I like to mire in the Turing tarpit? Scrolling through its manual, it probably helps. Oh well. – Huang_d Jun 18 '17 at 22:14
9
+150

TikZ is inherently 2D. You can perhaps do something like the following, but on the other hand it might not be good enough for you.

Note that I edited the image with Gimp to remove the white background, and saved it as a PNG with transparency:

enter image description here

Output:

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\XRad}{6}
\pgfmathsetmacro{\YRad}{2}
\draw [black!50,very thick] (-\XRad,0) arc[start angle=180,delta angle=-180,x radius=\XRad cm,y radius=\YRad cm];
\node [inner sep=0pt,outer sep=0pt] (heart) at (0,0) {\includegraphics[scale=2]{heart}};
\draw [black!50,very thick] (-\XRad,0) arc[start angle=180,delta angle=180,x radius=\XRad cm,y radius=\YRad cm];

\draw [black!20,line width=2mm] (30:\XRad cm) arc[start angle=30,end angle=240,radius=\XRad cm];
\draw [decoration={
    text along path,
    text={|\tiny| Abnormal right axis deviation},
    text effects/.cd,
    character widths={inner sep=-2pt}
    },
    decorate] (230:\XRad cm-0.5mm) arc[start angle=230,delta angle=-50,radius=\XRad cm-0.5mm];


% example of node on polar arc
\node [rotate=-25] (III) at (243:\XRad cm) {III};
\node [rotate=-25] at (243:\XRad cm+5mm) {$+120^{\circ}$};

\draw [-stealth,blue!60,thick] (III) -- (-1.5,-2.5);


% example of node on equatorial arc
\node [rotate=-30,font=\bfseries] (V9) at (30:\XRad cm-2mm and \YRad cm-1mm) {V9};
\foreach \ANG in {30,20,5} 
  \draw (\ANG:\XRad cm and \YRad cm) -- (0,0);

\end{tikzpicture}
\end{document}
  • Hi, @TorbjornT. Your picture is very nice! Could you explain, please, the meaning of delta angle inside the \draw options? I am trying to understand hou you got the heart to look inside the ellipse (i.e., the top part of ellipse behind the heart while the bottom part in front of it). Thank you in advance! – Brasil Nov 17 '18 at 14:10
  • 1
    @Brasil delta angle is how many degrees of the complete ellipse should be drawn, starting at start angle. I first draw the top part of the ellipse, then add the heart, and then draw the bottom part of the ellipse. – Torbjørn T. Nov 17 '18 at 14:28
  • Great. Now I got it! Thank you, @TorbjornT. – Brasil Nov 17 '18 at 14:29
9
+300

I have added this as a new answer since the approach is different from my previous work.


3D is possible and it is surprisingly easy. Well, it is still fake by any means (occlusion for example still depends on drawing order) but you can now place points on the canvas based on radius, phi and theta. The important word here is points: All arc or curve to functions do not respect 3D (neither this one nor any prior instance) and therefore have to be drawn by eye. That also means that if you want to draw a circle properly, you will have to do that with a finely graded \foreach.

The coordinate system is defined on top of the existing xyz coordinate system, mapping to it via the coordinate transformation as given on wikipedia. Angles are to be given in degree, phi ∈ [0:360], theta ∈ [0:180]. There is residue slanting due to the xyz system being naturally turned. For completion, I have build a spherical system around each axis, i.e. longitude around each axis.

Pictures of each spherical coordinate system: (click to enlarge)

longitude around x longitude around y longitude around z

This then enables you to reference points based on a spherical system. An improved version of the heart drawing is found below. Note that occlusion depends on the order of drawing, not on 3D position. The polar grid overlaps the heart in the back because it is drawn after it (in terms of code). Note that there appears to be a problem with angle calculation, as the labels of the grid are significantly distorted. If you use something like this, either make the pins long enough or go for debugging. Maybe the mistake is obvious, I have not spent much time it. Wiser minds are invited to comment below.

Heart amended Figure 1, a heart with pins in it.


Finally, there is code for coordinate calculation that gives a spherical coordinate system.

%along x axis
\makeatletter
\define@key{x sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{x sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{x sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{x spherical}{% %%%rotation around x
    \setkeys{x sphericalkeys}{#1}%
    \pgfpointxyz{\myradius*cos(\mytheta)}{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*sin(\mytheta)*sin(\myphi)}}


%along y axis
\makeatletter
\define@key{y sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{y sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{y sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{y spherical}{% %%%rotation around x
    \setkeys{y sphericalkeys}{#1}%
    \pgfpointxyz{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*cos(\mytheta)}{\myradius*sin(\mytheta)*sin(\myphi)}}


%along z axis
\makeatletter
\define@key{z sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{z sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{z sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{z spherical}{% %%%rotation around x
    \setkeys{z sphericalkeys}{#1}%
    \pgfpointxyz{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*sin(\mytheta)*sin(\myphi)}{\myradius*cos(\mytheta)}}

The code is pretty much the same in all three instances; Define three variables, one each for radius, theta and phi. Define new coordinate system [xyz] spherical and map the new coordinates to each entry in the xyz coordinate system. The [xyz] system is then a permutation of to which coordinate to map each coordinate transformation. The three spheres are drawn with variations of

\begin{tikzpicture}
\draw[->] (0,0,0) -- (4,0,0) node[at end, below right, gray]{x};
\draw[->] (0,0,0) -- (0,4,0) node[at end, above left, gray]{y};
\draw[->] (0,0,0) -- (0,0,4) node[at end, below left, gray]{z};
\foreach \one in {0,10,...,180}
    \foreach \two in {220, 230,...,360}
        \draw {--  (y spherical cs: radius=3, theta=\one, phi=\two) circle (0.5pt)};
\end{tikzpicture}

The code for figure 1 is given below. For the text on the gray labels, it now requires usetikzlibrary{decorations.text}.

\begin{tikzpicture}
%side gray strips and label on it
\draw[line width = 10pt, gray!40] (y spherical cs: radius=5.5, phi=180, theta=135) foreach \angle in {134, 133,...,90} {-- (y spherical cs: radius = 5.5, phi=180, theta=\angle)} -- (y spherical cs: radius=5, phi=180, theta=90);
\path decorate [decoration={text along path, text={Bottom left label},text align= {align=center},reverse path}] {(y spherical cs: radius=5.5, phi=180, theta=135) foreach \angle in {134, 133,...,90} {-- (y spherical cs: radius = 5.6, phi=180, theta=\angle)}};

\draw[line width = 10pt, gray!40] (y spherical cs: radius = 5, phi= 180, theta=90) foreach \angle in {90, 89,...,0} { -- (y spherical cs: radius = 5.5, phi=180, theta=\angle)} -- (y spherical cs: radius = 5, phi = 0, theta= 0);
\path decorate [decoration={text along path, text={Bottom left label},text align= {align=center}}] {(y spherical cs: radius = 5, phi= 180, theta=90) foreach \angle in {90, 89,...,0} { -- (y spherical cs: radius = 5.4, phi=180, theta=\angle)}};

%3D coordinate system
\draw[->] (0,0,0) -- (7,0,0) node[at end, below right, gray]{x};
\draw[->] (0,0,0) -- (0,7,0) node[at end, above left, gray]{y};
\draw[->] (0,0,0) -- (0,0,7) node[at end, below left, gray]{z};

%Stole my heart
\draw (0,0) node (heart) {\includegraphics[width=5cm]{QwMQn}};

%numbered lables with pricks
\foreach \angle in {20,46,...,280}{
    \path (y spherical cs: radius = 5, phi = \angle,theta = 60) node (Outer\angle) {};
    \path (y spherical cs: radius = 2, phi = \angle, theta = 60) node (Inner\angle) {};
    \draw (Inner\angle) -- (Outer\angle) node {\angle};}

%coordinate system in the plane – Note that the coordinate calculation for outer and inner group seems strange
\draw (y spherical cs: radius = 5, phi = 0, theta= 90) foreach \aangle in {1,2,...,359} { -- (y spherical cs: radius = 5, phi = \aangle, theta = 90)} -- cycle;
\draw (y spherical cs: radius = 5.5, phi=30, theta=90) node[gray] {$\phi$};
\foreach \angle in {0,10,...,350}{
    \path (y spherical cs: radius = 5.2, phi = \angle,theta = 90) node (Outer\angle) {};
    \path (y spherical cs: radius = 4.5, phi = \angle, theta = 90) node (Inner\angle) {};
    \draw (Inner\angle) -- (Outer\angle);}

%Theta angle on the side
\draw[->] (y spherical cs: radius = 5, phi = 0, theta= 70) foreach \aangle in {71,71.2,...,160} { -- (y spherical cs: radius = 5, phi = 0, theta = \aangle)};
\draw (y spherical cs: radius = 5.5, phi=0, theta=120) node[gray] {$\theta$};
\end{tikzpicture}

The coordinate code works out of the box, no library required. I hope this helps you. I extend my gratitude @Tom Bombadil for the answer in the shift and rotate in 3D question, pointing out that cos and sin are usable within the low-level pgf keys.

  • 1
    @LéoLéopoldHertz준영 Like this? You draw circles, spirals and whatever curves you can express with proper \foreach syntax. – Huang_d Jun 19 '17 at 12:32
  • 1
    @LéoLéopoldHertz준영 I am unsure as to what exactly you are referring to. Please see the amended answer. If something is still unclear, feel free to point me to it. – Huang_d Jun 19 '17 at 16:18
  • Looks even better! - - The lines etc 176, ... should intersect with thick gray circle. Can this requirement be met? I am mathematically evaluating that everything is correct in your plot. - - Somehow, the thick gray circle should be fixed to the plane where z-axis is on. Does this plane have a normal in your plot? – Léo Léopold Hertz 준영 Jun 19 '17 at 16:29
  • 1
    @LéoLéopoldHertz준영 There are no intersections here because these are blocks of 3D code projected to a 2D plane. What is in front and back depends on its position in the code, not its geometrical position. I can of course extend the lines, but the result would be all in front because the gray ring is drawn first. For the proper 3D effect, you have to split the foreach at 176 and continue with 202 on the background layer. – Huang_d Jun 19 '17 at 16:32
  • 1
    Can such a problem somehow be overpassed? I do not understand why intersections are not allowed. Ahh, .., thinking. – Léo Léopold Hertz 준영 Jun 19 '17 at 16:33
0

We discussed with Huang_d here the following followup problems for the situation where Turing complete, 1000x more CPU power than today (GPU) and Al because of the problem in the approach here

  1. There are two intersecting planes. How can you calculate the intersection of the two so that you can put the proper one in front?

....

  1. How can you save the z position into an z-buffer array for later drawing?

....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.