Drawing an arc between two 3D points - tikz

I am trying to draw composite 3D shapes, and I am struggling drawing arcs between two 3D points. In the example below I would like to draw a dashed arc of 180 degrees between from D to H clockwise, and a solid arc of 180 degrees from D to H anti-clockwise. However, when I try
\draw (D) arc[radius=\R, start angle=180, end angle=0];
I don't get the arc I want. Below is the code I have so far:
\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\begin{document}
\tdplotsetmaincoords{65}{-43}
\begin{center}
\begin{tikzpicture}[
scale=1,
tdplot_main_coords]
\def\R{2}
\def\h{6}
\coordinate (A) at ({\R*cos(0)},{\R*sin(0)},0);
\coordinate (B) at ({\R*cos(45)},{\R*sin(45)},0);
\coordinate (C) at ({\R*cos(90)},{\R*sin(90)},0);
\coordinate (D) at ({\R*cos(135)},{\R*sin(135)},0);
\coordinate (E) at ({\R*cos(180)},{\R*sin(180)},0);
\coordinate (F) at ({\R*cos(225)},{\R*sin(225)},0);
\coordinate (G) at ({\R*cos(270)},{\R*sin(270)},0);
\coordinate (H) at ({\R*cos(315)},{\R*sin(315)},0);
\coordinate (O) at (0,0,0);
\coordinate (O') at (0,0,\h);
\coordinate (O'') at (0,0,-\h);
\foreach \i in {A,B,C}{
\draw[dashed] (\i) -- (O');
\node at (\i) [above]{$\i$};}
\foreach \i in {D,E,F,G,H}{
\draw (\i) -- (O');
\node at (\i) [below]{$\i$};}
\draw[red] (O) circle (\R);
\draw[red] (D) -- (O'') -- (H);
\draw[dashed] (H) -- (A) -- (B) -- (C) -- (D);
\draw (D) -- (E) -- (F) -- (G) -- (H);
\node at (O') [above]{$O'$};
\node at (O'') [below,thick,red]{$O''$};
\end{tikzpicture}
\end{center}
\end{document}

Since nobody answered or commented, I came up with my own solution, which is using a two-coordinate system instead of three, but it works...
\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\begin{document}
\begin{center}
\begin{tikzpicture}[scale=1]
\def\xRadius{2}
\def\yRadius{0.4*\xRadius}
\def\h{5.4}
\coordinate (A) at ({\xRadius*cos(45)},{\yRadius*sin(45)});
\coordinate (B) at ({\xRadius*cos(90)},{\yRadius*sin(90)});
\coordinate (C) at ({\xRadius*cos(135)},{\yRadius*sin(135)});
\coordinate (D) at ({\xRadius*cos(180)},{\yRadius*sin(180)});
\coordinate (E) at ({\xRadius*cos(225)},{\yRadius*sin(225)});
\coordinate (F) at ({\xRadius*cos(270)},{\yRadius*sin(270)});
\coordinate (G) at ({\xRadius*cos(315)},{\yRadius*sin(315)});
\coordinate (H) at ({\xRadius*cos(0)},{\yRadius*sin(0)});
\coordinate (O) at (0,0);
\coordinate (O') at (0,\h);
\coordinate (O'') at (0,-\h);
\foreach \i in {A,B,C}{
\draw[dashed] (\i) -- (O');
\node at (\i) [above]{$\i$};}
\foreach \i in {D,E,F,G,H}{
\draw (\i) -- (O');
\node at (\i) [below]{$\i$};}
\draw[red,dashed] (H) arc [x radius = \xRadius, y radius = \yRadius, start angle=0, end angle=180];
\draw[red] (H) arc [x radius = \xRadius, y radius = \yRadius, start angle=0, end angle=-180];
\draw[red] (D) -- (O'') -- (H);
\draw[dashed] (H) -- (A) -- (B) -- (C) -- (D);
\draw (D) -- (E) -- (F) -- (G) -- (H);
\node at (O') [above]{$O'$};
\node at (O'') [below,thick,red]{$O''$};
\end{tikzpicture}
\end{center}
\end{document}

Related

LateX Tikz: How can I rotate a line

I tried to rotate a line, several lines, with scope, but I don't know how.
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{arrows}
\begin{document}
\begin{tikzpicture}[]
\coordinate (A) at (0,0);
\coordinate (B) at (4,0);
\coordinate (C) at (6,2);
\coordinate (D) at (2,2);
\begin{scope}[rotate=30]
\draw (A) -- (B) --(C) -- (D) --cycle;
\end{scope}
\begin{scope}[rotate=60]
\draw (2,0) ellipse (3 cm and 1.5cm);
\end{scope}
\end{tikzpicture}
\end{document}
I'm expecting a rotated parallelogram by 30°.
I tried a rotation of an ellipse. This works.
The problem is that you are using absolute coordinates. If you replace them by relative coordinates, you'll get rotated shapes:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{arrows}
\begin{document}
\begin{tikzpicture}[]
\coordinate (A) at (0,0);
\coordinate (B) at (4,0);
\coordinate (C) at (6,2);
\coordinate (D) at (2,2);
\begin{scope}[rotate=30]
\draw (A) -- ++(0,1) -- ++(1,0) -- ++(0,-1) --cycle;
\draw (D) rectangle ++(3,3);
\end{scope}
\begin{scope}[rotate=60]
\draw (2,0) ellipse (3 cm and 1.5cm);
\end{scope}
\end{tikzpicture}
\end{document}
Now if you wanted to keep your absolute coordinates, you could transform the canvas:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{arrows}
\begin{document}
\begin{tikzpicture}[]
\coordinate (A) at (0,0);
\coordinate (B) at (4,0);
\coordinate (C) at (6,2);
\coordinate (D) at (2,2);
\begin{scope}[transform canvas={rotate=30}]
\draw (A) -- (B) --(C) -- (D) --cycle;
\end{scope}
\begin{scope}[rotate=60]
\draw (2,0) ellipse (3 cm and 1.5cm);
\end{scope}
\end{tikzpicture}
\end{document}

To color the two regions separated by a parabolic function with different colors respectively using tikz (The function as the boundary)

Could someone give some suggestions? I want to color the two areas of the rectangle with blue and yellow respectively, as shown in the picture. The function is as the boundary between the two regions.
Here is my code and expected result.
\documentclass[border=2mm]{standalone}
\usepackage{pgfplots}
\usepackage{tikz}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\begin{scope}[shorten >=1pt,-,draw=black!80, node distance=\layersep]
\begin{axis}[
width=8.8cm,
enlargelimits=false,
axis on top,
point meta=explicit,
height=6.5cm,
xlabel={},
ylabel={},
xtick=\empty,
ytick=\empty,
xmin=-8,
xmax=8,
ymin=-10,
ymax=1,
xlabel={\large $x$},
ylabel={\large $y$},
%ylabel style={yshift=0.0cm},
yticklabels={},
xticklabel style = {font=\large,yshift=0.0ex},
colorbar style={
font =\Large
},
]
\addplot [thick]{-0.8*(x-1)^2};
\end{axis}
\end{scope}
\end{tikzpicture}
\end{document}
\documentclass[border=2mm]{standalone}
\usepackage{pgfplots}
\usepackage{tikz}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\begin{scope}[shorten >=1pt,-,draw=black!80, node distance=\layersep]
\begin{axis}[
width=8.8cm,
enlargelimits=false,
axis on top,
point meta=explicit,
height=6.5cm,
xlabel={},
ylabel={},
xtick=\empty,
ytick=\empty,
xmin=-8,
xmax=8,
ymin=-10,
ymax=1,
xlabel={\large $x$},
ylabel={\large $y$},
%ylabel style={yshift=0.0cm},
yticklabels={},
xticklabel style = {font=\large,yshift=0.0ex},
colorbar style={
font =\Large
},
axis background/.style={fill=yellow},
]
\addplot [thick,fill=blue]{-0.8*(x-1)^2};
\end{axis}
\end{scope}
\end{tikzpicture}
\end{document}

Get line width and inner sep of a TikZ node

Is it possible to retrieve a node's inner sep and line width using the key tree? My exact use case is below.
I want to find the coordinates of the red marks in the image below, but not using the method I've used below. Basically I want what would be the north east anchor (or some other anchor on a rectangle) if it were to sit in the middle of the border line instead of the outer edge, as well as if it were to lie on the node's contents before inner sep is added. I don't want to use duplicate "phantom" nodes as I have below because in my use case the node's contents might be messy.
I also realize I can just save the line width and inner sep globally by using \pgfmathsetlength{}{}, applying them to the node and using the same macros to navigate relative to north east, or in similar fashion by defining custom keys. But I'd really like to ask the node directly, as though these values were specified as literals in the node's options like \node [inner sep=1.2em] {};.
Image:
Code:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\node [draw, line width=5pt, inner sep=8pt] (A) {foo};
\node [draw=cyan, line width=2pt, inner sep=8pt] (B) {\phantom{foo}};
\node [line width=0pt, inner sep=0pt] (C) {\phantom{foo}};
\node [line width=0pt, inner sep=8pt] (D) {\phantom{foo}};
% Basically I don't want to use nodes C and D, I want everything relative to A
\draw [red] plot [mark=x] coordinates { (C.north east) };
\draw [red] plot [mark=x] coordinates { (D.north east) };
\draw [green] plot [mark=x] coordinates { (A.north east) };
\end{tikzpicture}
\end{document}

Precise and smooth curve with Tikz

I'm trying to draw some curves, but it doesn't work out very well.
what I need
what I get
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
ticks=none,
xtick distance=1,
ytick distance=1,
axis equal image=true,
grid,
grid style={gray!50},
grid=both,
xlabel={$x$},
ylabel={$y$},
axis lines=middle,
xmin=-4, xmax=9, ymin=-5, ymax=4,
axis x line=center,
axis y line=center,
]
\addplot[thick, smooth] plot coordinates
{
(-3, -1)
(-.5, -3)
(.5, -1.9)
(1.5, -2.8)
(3.5, 1)
(5.5, 3)
(7.5, -1.95)
(8, -1.5)
};
\end{axis}
\end{tikzpicture}
\end{document}
Is it possible to build such smooth curves without adding a large number of points? In the original drawing, you can see several reference points. Is there any way to configure \addplot or any other command?
Using the added information that all those points (except the last one) have zero gradient, Bézier curves seem better suited than a smooth plot.
So, you may achieve this kind of thing...
with this bit of code...
\documentclass[border=2pt]{standalone}
\usepackage{fourier}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[thick, line cap=round, >=latex, scale=0.5]
% Some constants for the Bezier curve
\def\x{0.5}
\def\u{1.0}
\def\v{0.3}
\def\w{0.1}
% The grid, axes and labels
\draw[thin, gray!20, help lines] (-4.5 ,-4.5) grid (9.5 ,4.5);
\draw[very thick, ->] (-4.5, 0) -- (9.8, 0) node[above] {$x$};
\draw[very thick, ->] (0, -4.5) -- (0, 4.8) node[left] {$y$};
\path (-3, 0) coordinate (x1) node[above] {$-3$}
(0, 0) coordinate (x2) node[below] {$\quad0$}
(1, 0) coordinate (x3)
(8, 0) coordinate (x4) node[below] {$8$}
(0, 1) coordinate (y1) node[right] {$1$};
% ticks are really cumbersome
\draw[very thick] ($(x1)+(0,-\w)$) -- ($(x1)+(0,\w)$);
\draw[very thick] ($(x3)+(0,-\w)$) -- ($(x3)+(0,\w)$);
\draw[very thick] ($(x4)+(0,-\w)$) -- ($(x4)+(0,\w)$);
\draw[very thick] ($(y1)+(-\w,0)$) -- ($(y1)+(\w,0)$);
% Finally, the points...
\path (-3, -1) coordinate (A)
(-.5,-3) coordinate (B)
(.5, -1.9) coordinate (C)
(1.5,-2.8) coordinate (D)
(3.5, 1) coordinate (E)
(5.5, 3) coordinate (F) node[above] {$y=F(x)$}
(7.5,-1.95) coordinate (G)
(8, -1.5) coordinate (H);
% and the line with suitable gradients (after a bit trial and error)
\draw[ultra thick]
(A) ..controls +(\u, 0) and ( $(B) + (-\x, 0)$ )..
(B) ..controls +(\x, 0) and ( $(C) + (-\v, 0)$ )..
(C) ..controls +(\v, 0) and ( $(D) + (-\v, 0)$ )..
(D) ..controls +(\x, 0) and ( $(E) + (-\u, 0)$ )..
(E) ..controls +(\u, 0) and ( $(F) + (-\x, 0)$ )..
(F) ..controls +(\x, 0) and ( $(G) + (-\u, 0)$ )..
(G) ..controls +(\w, 0) and ( $(H) + (-\w,-\v)$ )..
(H);
% two small circles to mark the curve ends
\draw[thin, fill=white] (A) circle (3pt);
\draw[thin, fill=white] (H) circle (3pt);
\end{tikzpicture}
\end{document}

Bargraph Error in Tikzpicture

I don't know why the data on x-axis over leaping. I don't have any idea.
\documentclass[varwidth=true, border=2pt]{standalone} \usepackage{pgfplots}\begin{document}
\begin{tikzpicture}
\begin{axis}[
symbolic x coords={Coke-Classic,Diet Coke, Dr.Peppre,Pepsi Cola,Sprite,},
xtick=data
]
\addplot[ybar,fill=blue] coordinates {
(Coke-Classic, 38)
(Diet Coke, 16)
(Dr.Peppre, 10)
(Pepsi Cola, 26)
(Sprite, 10)
};
\end{axis}
\end{tikzpicture} \end{document}
There are two possible solutions, that came to my mind. Both are relatively easy (only one line has to be added):
Solution 1
To avoid overlapping x-labels, you can explicitly define the size of one x-unit:
\documentclass[varwidth=true, border=2pt]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
symbolic x coords={Coke-Classic,Diet Coke, Dr.Peppre,Pepsi Cola,Sprite,},
xtick=data,
x=2cm
]
\addplot[ybar,fill=blue] coordinates {
(Coke-Classic, 38)
(Diet Coke, 16)
(Dr.Peppre, 10)
(Pepsi Cola, 26)
(Sprite, 10)
};
\end{axis}
\end{tikzpicture}
\end{document}
The only thing I changed is adding x=2cm to the axis-options.
The result looks as follows:
Solution 2
The solution above increases the width of the plot. If you don't want this, you can instead rotate the tick labels:
\documentclass[varwidth=true, border=2pt]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
symbolic x coords={Coke-Classic,Diet Coke, Dr.Peppre,Pepsi Cola,Sprite,},
xtick=data,
xticklabel style={rotate=45}
]
\addplot[ybar,fill=blue] coordinates {
(Coke-Classic, 38)
(Diet Coke, 16)
(Dr.Peppre, 10)
(Pepsi Cola, 26)
(Sprite, 10)
};
\end{axis}
\end{tikzpicture}
\end{document}
Here I just replaced the x=2cm with xticklabel style={rotate=45} (45 is the rotation angle, you can use any other angle, just use what you think looks best).