TeX - LaTeX Asked on August 15, 2020
I am using the tikz-3dplot-circleofsphere
package to draw circles of a sphere using tikz-3dplot. Consider the following MWE from the documentation:
documentclass{standalone}
usepackage{tikz-3dplot-circleofsphere}
begin{document}
centering
defr{3}
tdplotsetmaincoords{60}{125}
begin{tikzpicture}[tdplot_main_coords]
draw[tdplot_screen_coords,thin,black!30] (0,0,0) circle (r);
foreach a in {-75,-60,...,75}
{tdplotCsDrawLatCircle[thin,black!29]{r}{a}}
foreach a in {0,15,...,165}
{tdplotCsDrawLonCircle[thin,black!29]{r}{a}}
tdplotCsDrawGreatCircle[red,thick,/.style={opacity=0}]{4}{105}{-23.5}
end{tikzpicture}
end{document}
which generates the following image
How can I get the dashed red line to appear when it is only behind the sphere. I.e. in this case I have chosen a radii for the red circle that is larger than that of the sphere.
My answer is not the shortest and maybe some of the elements I'm using are already defined somewhere in a TikZ library. For example, the observer's position and its influence on the 3D-2D parallel projection that TikZ applies in the background. But I need this position explicitly in order to deal with the "backside" of the sphere.
The drawing is made in three steps: 1) the 3D point of view, 2) the sphere, and 3) the circle (plane section of the sphere). It is inspired by the construction that I made for Drawing a wedge of a torus in Asymptote.
The hidden points on the sphere are detected by computing the inner product between the viewer vector and the position vector of the point. I decided to modify the opacity of the hidden elements because it was easier to code this way. If you want to have dashed lines, you must work on the summation indices and do something only when the index is even for example.
The code and then some explanations about the elements used in it according to the three steps above.
tikzmath{
real longit, latit, tox, toy, toz;
real newxx, newxy, newyx, newyy, newzx, newzy;
longit = 25;
latit = 32;
tox = cos(latit)*sin(longit);
toy = sin(latit);
toz = cos(latit)*cos(longit);
newxx = cos(longit); newxy = -sin(longit)*sin(latit);
newyy = cos(latit);
newzx = -sin(longit); newzy = -cos(longit)*sin(latit);
real R;
R = 3; % sphere radius
integer Sy, Sz, prevj, prevk, C; % for loops (sphere and circle)
Sy = 96; % 96; % must be divisible by 8
Sz = 48; % 48; % must be divisible by 4
C = 45; % nb of points for the curve
real nlon, nlat, d, r;
real ux, uz, vx, vy, vz, nx, ny, nz;
d = 1.5;
r = sqrt(R^2-d^2);
nlon = 95; nlat = 15;
nx = cos(nlat)*sin(nlon);
ny = sin(nlat);
nz = cos(nlat)*cos(nlon);
ux = cos(nlon);
uz = -sin(nlon);
vx = -sin(nlat)*sin(nlon);
vy = cos(nlat);
vz = -sin(nlat)*cos(nlon);
function Sx(j, k) { % the x component of the normal vector associated to Pjk
return sin(180*(k/Sz))*cos(360*(j/Sy));
};
function Sy(j, k) {
return cos(180*(k/Sz));
};
function Sz(j, k) {
return sin(180*(k/Sz))*sin(360*(j/Sy));
};
function isSeen(j, k) {
let res = Sx(j,k)*tox + Sy(j,k)*toy + Sz(j,k)*toz;
if res>0 then {return 1;} else {return .35;};
};
function Cx(t) {
return r*ux*cos(t) + r*vx*sin(t) + d*nx;
};
function Cy(t) {
return r*vy*sin(t) + d*ny;
};
function Cz(t) {
return r*uz*cos(t) + r*vz*sin(t) + d*nz;
};
function CIsSeen(j) {
let res = Cx(360*(j/C))*tox + Cy(360*(j/C))*toy
+ Cz(360*(j/C))*toz;
if res>0 then {return 1;} else {return .3;};
};
}
begin{tikzpicture}[every node/.style={scale=.8},
x={(newxx cm, newxy cm)},
y={(0 cm, newyy cm)},
z={(newzx cm, newzy cm)}
]
% coordinate system first layer
draw[green!50!black, thin, opacity=.3]
(0, 0, 0) -- (R, 0, 0)
(0, 0, 0) -- (0, R, 0)
(0, 0, 0) -- (0, 0, R);
%%% sphere
% longitude circles
foreach j in {4, 8, ..., Sy}{%
foreach k [remember=k as prevk (initially 0)] in {1, ..., Sz}{
draw[gray!90, very thin, opacity={isSeen(j, k)}, scale=R]
({Sx(j,prevk)}, {Sy(j,prevk)}, {Sz(j,prevk)})
-- ({Sx(j,k)}, {Sy(j,k)}, {Sz(j,k)});
}
}
% latitude circles
foreach k in {4, 8, ..., Sz}{%
foreach j [remember=j as prevj (initially 0)] in {1, ..., Sy}{%
draw[gray!90, very thin, opacity={isSeen(j, k)}, scale=R]
({Sx(prevj,k)}, {Sy(prevj,k)}, {Sz(prevj,k)})
-- ({Sx(j,k)}, {Sy(j,k)}, {Sz(j,k)});
}
}
% plane section
foreach j [evaluate=j as t using 360*(j/C)] in {0, 1, ..., C}{%
path ({Cx(t)}, {Cy(t)}, {Cz(t)}) coordinate (P-j);
}
foreach j [remember=j as prevj (initially 0)] in {1, ..., C}{%
draw[violet, thick, opacity={CIsSeen(j)}] (P-prevj) -- (P-j);
}
% another plane section
tikzmath{
d = 0; % big circle
r = sqrt(R^2-d^2);
nlon = 70; nlat = 110;
nx = cos(nlat)*sin(nlon);
ny = sin(nlat);
nz = cos(nlat)*cos(nlon);
ux = cos(nlon);
uz = -sin(nlon);
vx = -sin(nlat)*sin(nlon);
vy = cos(nlat);
vz = -sin(nlat)*cos(nlon);
}
foreach j [evaluate=j as t using 360*(j/C)] in {0, 1, ..., C}{%
path ({Cx(t)}, {Cy(t)}, {Cz(t)}) coordinate (P-j);
}
foreach j [remember=j as prevj (initially 0)] in {1, ..., C}{%
draw[red, thick, opacity={CIsSeen(j)}] (P-prevj) -- (P-j);
}
% coordinate system second layer
draw[green!50!black, thin, ->]
(R, 0, 0) -- (6, 0, 0) node[right] {$x$};
draw[green!50!black, thin, ->]
(0, R, 0) -- (0, 6, 0) node[above] {$y$};
draw[green!50!black, thin, ->]
(0, 0, R) -- (0, 0, 6.5) node[below left] {$z$};
% normal vector to big circle
draw[red, thick, opacity=.35] (0, 0, 0) -- ($R*(nx, ny, nz)$);
draw[red, thick, -{Latex[length=7pt, width=6.5pt]}]
($R*(nx, ny, nz)$) -- ($1.6*R*(nx, ny, nz)$)
node[left, text width=6.5em, inner sep=0pt] {normal vector to red circle};
end{tikzpicture}
The sphere is drawn centered at the origin of the coordinate system. In TikZ, the coordinate plane Oxy corresponds to the screen and Oz points outside the screen, towards the viewer.
The screen (plane on which the image is drawn as seen by the viewer) is the plane passing through the origin and orthogonal to w. The orthonormal basis that induces the coordinate system of the screen is given by (u, v, w), where u = (cos(longit), 0 , -sin(longit) and v = (-sin(longit) sin(latit), cos(latit), -cos(longit) sin(latit)). The vector u is parallel to Oxz.
The points (1,0,0), (0,1,0), and (0,0,1) project onto points described in the global options of the drawing by x={(newxx cm,newxy cm)}, etc, with newxx = <(1,0,0), u>, newxy = <(1,0,0), v> and so on.
The transparency of the hidden elements is controlled through the function isSeen(j, k) which returns 1 if the inner product of the position vector corresponding to P-j-k with the observer's vector is positive and a lesser value if not.
Note that in order to diminish the execution time, the points of the mesh are not defined as TikZ coordinate elements. In any case, such a definition would not allow us to recuperate the three components of a point.
More than one circle can be drawn by redefining its corresponding elements (normal vector and distance for the plane that contains it).
In case you need the intersection points of two such plane sections, you have to define them as whole TikZ elements (through the path command) to be able to use the option name path on them.
Answered by Daniel N on August 15, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP