%%% on January 19, 2026 %%% \tikzmath{% function hyperplane(\varx, \vary, \varz) {% return \coefHx*\varx +\coefHy*\vary +\coefHz*\varz +\coefH; }; } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% General functions for the construction of the trace of a surface %%%% of revolution in a half space determined by H>0 \tikzmath{% function PPNorm(\k, \j, \i) {% return norm3d(\PPx{\k,\j,\i}, \PPy{\k,\j,\i}, \PPz{\k,\j,\i}); }; function nFaceHx(\l1, \m1, \ru1, \l2, \m2, \ru2) {% return \PPy{\l1,\m1,\ru1}*\PPz{\l2,\m2,\ru2} -\PPz{\l1,\m1,\ru1}*\PPy{\l2,\m2,\ru2}; }; function nFaceHy(\l1, \m1, \ru1, \l2, \m2, \ru2) {% return \PPz{\l1,\m1,\ru1}*\PPx{\l2,\m2,\ru2} -\PPx{\l1,\m1,\ru1}*\PPz{\l2,\m2,\ru2}; }; function nFaceHz(\l1, \m1, \ru1, \l2, \m2, \ru2) {% return \PPx{\l1,\m1,\ru1}*\PPy{\l2,\m2,\ru2} -\PPy{\l1,\m1,\ru1}*\PPx{\l2,\m2,\ru2}; }; } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Code elements \tikzset{% points and H position/.code={% used in |sor H| % Creates the list \positionH which takes values -4, 0, 1 % depending on the position of the point \P with respect to H. \tikzmath{% integer \positionH; \coefHx = \ux*\aVar1 +\vx*\aVar2 +\wx*\aVar3; \coefHy = \uy*\aVar1 +\vy*\aVar2 +\wy*\aVar3; \coefHz = \uz*\aVar1 +\vz*\aVar2 +\wz*\aVar3; for \j in {0, ..., \NParallels}{% for \k in {0, ..., \NMeridians}{% \val = hyperplane(\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}); if \val >= 0 then {% if \val < \nearZero then {% \positionH{\k,\j} = 0; } else {% \positionH{\k,\j} = 1; }; } else {% if \val > -\nearZero then {% \positionH{\k,\j} = 0; } else {% \positionH{\k,\j} = -4; }; }; }; }; } }, new points on meridians and H/.code={% % Points are costructed if there are two different proper vertices % with repect to H on a meridian. Each time, the new point takes % the indices of the vertex that lies in the negative half-space % with a third position which equals either 2 or 4, depending on % the order of the two vertices along the meridian (2 if -4 goes % forward to become 0 and 4 if backward). % % Uses the list \positionH defined in |points and H position|. \tikzmath{% integer \prevPosition, \currentPosition; % along every meridian for \k in {0, ..., \NMeridians}{% \prevPosition = \positionH{\k,0}; for \j in {1, ..., \NParallels}{% \currentPosition = \positionH{\k,\j}; if \prevPosition*\currentPosition <= 0 then {% <>0 and one =0 if \prevPosition +\currentPosition < -1 then {% <0 and >=0 \prevj = \j -1; \val0 = hyperplane(\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}); \val1 = hyperplane(\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}); \uTmp = (\Px{\k,\prevj}*\val1 -\Px{\k,\j}*\val0)/(\val1 -\val0); \vTmp = (\Py{\k,\prevj}*\val1 -\Py{\k,\j}*\val0)/(\val1 -\val0); \wTmp = (\Pz{\k,\prevj}*\val1 -\Pz{\k,\j}*\val0)/(\val1 -\val0); if \currentPosition == -4 then {% \Px{\k,\j,4} = \uTmp; \Py{\k,\j,4} = \vTmp; \Pz{\k,\j,4} = \wTmp; } else { \Px{\k,\prevj,2} = \uTmp; \Py{\k,\prevj,2} = \vTmp; \Pz{\k,\prevj,2} = \wTmp; }; }; }; \prevPosition = \positionH{\k,\j}; }; }; } }, new points on parallels and H/.code={% % Points are costructed if there are two different proper vertices % with repect to H on a parallel. Each time, the new point takes % the indices of the vertex that lies in the negative half-space % with a third position which equals either 1 or 3, depending on % the order of the two vertices along a parallel (1 if -4 goes % forward to its destiny...). % % Uses the list \positionH defined in |points and H position|. \tikzmath{% integer \prevPosition, \currentPosition; % along every parallel for \j in {0, ..., \NParallels}{% \prevPosition = \positionH{0,\j}; % initialize \prevPosition for \k in {1, ..., \NMeridians}{% \currentPosition = \positionH{\k,\j}; if \prevPosition *\currentPosition <= 0 then {% <>0 and one =0 if \prevPosition +\currentPosition < -1 then {% <0 and >=0 \prevk = int(Mod(\k -1, \NMeridians)); \val0 = hyperplane(\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}); \val1 = hyperplane(\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}); \uTmp = (\Px{\prevk,\j}*\val1 -\Px{\k,\j}*\val0)/(\val1 -\val0); \vTmp = (\Py{\prevk,\j}*\val1 -\Py{\k,\j}*\val0)/(\val1 -\val0); \wTmp = (\Pz{\prevk,\j}*\val1 -\Pz{\k,\j}*\val0)/(\val1 -\val0); if \currentPosition == -4 then {% \Px{\k,\j,3} = \uTmp; \Py{\k,\j,3} = \vTmp; \Pz{\k,\j,3} = \wTmp; } else { \Px{\prevk,\j,1} = \uTmp; \Py{\prevk,\j,1} = \vTmp; \Pz{\prevk,\j,1} = \wTmp; }; }; }; \prevPosition = \positionH{\k,\j}; }; }; } }, drawing weights/.code={% % Construct drawning weights, \drawWeight, for each % quadrilateral. Each point has a weight, \positionH, with % respect to $H$'s equation, $1$, $0$, or $-4$. % The drawing weight is the sum of these weights. % Starts the construction of |\toBeDrawn|. \tikzmath{% integer \drawWeightTmp; for \j in {1, ..., \NParallels}{% \prevj = \j -1; for \k in {0, ..., \NMeridians}{% \prevk = int(Mod(\k -1, \NMeridians)); \drawWeightTmp = \positionH{\prevk,\prevj} +\positionH{\k,\prevj} +\positionH{\k,\j} +\positionH{\prevk,\j}; \drawWeight{\k,\j} = int(\drawWeightTmp); }; }; } }, } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Main style and pic objects \tikzset{% sor and H/.style args={name=#1, meridians=#2, parallels=#3, t_ini=#4, t_end=#5, rAxis=#6, cHyperplane=#7}{% evaluate={% real \s, \t, \ipFTo, \ipFTo; real \cax, \sax, \cay, \say, \caz, \saz; real \ux, \uy, \uz, \vx, \vy, \vz, \wx, \wy, \wz; real \coefHx, \coefHy, \coefHz, \coefH; integer \NMeridians, \NParallels; integer \j, \k, \i, \prevj, \prevk; \NMeridians = #2; \NParallels = #3; \initialT = #4; \finalT = #5; \i = 0; for \tmp in {#6}{% angles that characterise the axis of % rotation's position; in fact the new basis % obtained by the compositon R_\ay R_\az R_\ax. \i = \i +1; \aVar\i = \tmp; }; \cax = cos(\aVar1); \sax = sin(\aVar1); \cay = cos(\aVar2); \say = sin(\aVar2); \caz = cos(\aVar3); \saz = sin(\aVar3); \i = 0; for \tmp in {#7}{% coefficients definig the hyperplane \i = \i +1; \aVar\i = \tmp; }; \coefHx = \aVar1; \coefHy = \aVar2; \coefHz = \aVar3; \coefH = \aVar4; }, new basis, the points={#1}, points and H position, % Transforms also the coefficients of H % according to the new basis. drawing weights, new points on parallels and H, new points on meridians and H, face normal vector and ips }, pics/rSurface and H/.style args={above=#1, below=#2, actions=#3}{% !! % #1 = fg layer % #2 = bg layer % #3 = actions code={% \tikzmath{% integer \j, \k, \prevk, \prevj, \layerI; } %% faces \foreach \k [evaluate=\k as \prevk using int(\k -1)] in {1, ..., \NMeridians}{% \foreach \j [evaluate=\j as \prevj using int(\j -1)] in {1, ..., \NParallels}{% \tikzmath{% \layerI = whatLayer(\ipFTo{\k,\j}, #1, #2); } \ifnum \drawWeight{\k,\j} > -1% no negative vertex \begin{pgfonlayer}{\layerI} \path[., #3] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \else% at least one negative vertex \ifnum \drawWeight{\k,\j} > -5% one negative vertex \oneNegativeVertex{#3}{0}% 1=in light \else% at least two negative vertices \ifnum \drawWeight{\k,\j} > -9 % two negative vertices \twoNegativeVertices{#3}{0} \else% three negative vertices \ifnum \drawWeight{\k,\j} > -13% three negative vertices \threeNegativeVertices{#3}{0} \fi \fi \fi \fi } } } }, pics/rSurface and HL/.style args={above=#1, below=#2, actions=#3}{% % #1 = fg layer % #2 = bg layer % #3 = actions (drawn must be provided if full opacity code={% \setColorsForRSurface \tikzmath{% integer \j, \k, \prevk, \prevj, \layerI, \rgbCst, \li; } %% faces \foreach \k [evaluate=\k as \prevk using int(\k -1)] in {1, ..., \NMeridians}{% \foreach \j [evaluate=\j as \prevj using int(\j -1)] in {1, ..., \NParallels}{% \tikzmath{% \layerI = whatLayer(\ipFTo{\k,\j}, #1, #2); \li = rgbLeftIndex(\ipFTo{\k,\j}, \ipFSun{\k,\j}); \rgbCst = rgbConstant(\ipFTo{\k,\j}, \ipFSun{\k,\j}); } \ifnum \drawWeight{\k,\j} > -1% no negative vertex \begin{pgfonlayer}{\layerI} \path[with L={1}, #3] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \else% at least one negative vertex \ifnum \drawWeight{\k,\j} > -5% one negative vertex \oneNegativeVertex{#3}{1}% 1=in light \else% at least two negative vertices \ifnum \drawWeight{\k,\j} > -9 % two negative vertices \twoNegativeVertices{#3}{1} \else% three negative vertices \ifnum \drawWeight{\k,\j} > -13% three negative vertices \threeNegativeVertices{#3}{1} \fi \fi \fi \fi } } } }, pics/partial rSurface and H/.style args={above=#1, below=#2, actions=#3, i from=#4, i to=#5}{% % #1 = fg layer % #2 = bg layer % #3 = actions % #4 = index of the first meridian % #5 = index of the last meridian code={% \tikzmath{% integer \j, \k, \prevk, \prevj, \layerI, \rgbCst, \kini, \kend; if #4 < #5 then {% \kini = int(#4 +1); \kend = #5; } else {% \kini = #4; \kend = int(#5 +1); }; } %% faces \foreach \k [evaluate=\k as \prevk using {int(Mod(\k -1, \NMeridians))}] in {\kini, ..., \kend}{% \foreach \j [evaluate=\j as \prevj using int(\j -1)] in {1, ..., \NParallels}{% \tikzmath{% \layerI = whatLayer(\ipFTo{\k,\j}, #1, #2); } \ifnum \drawWeight{\k,\j} > -1% no negative vertex \begin{pgfonlayer}{\layerI} \path[., #3] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \else% at least one negative vertex \ifnum \drawWeight{\k,\j} > -5% one negative vertex \oneNegativeVertex{#3}{0}% 1=in light \else% at least two negative vertices \ifnum \drawWeight{\k,\j} > -9 % two negative vertices \twoNegativeVertices{#3}{0} \else% three negative vertices \ifnum \drawWeight{\k,\j} > -13% three negative vertices \threeNegativeVertices{#3}{0} \fi \fi \fi \fi } } } }, pics/partial rSurface and HL/.style args={above=#1, below=#2, actions=#3, i from=#4, i to=#5}{% % #1 = fg layer % #2 = bg layer % #3 = actions % #4 = index of the first meridian % #5 = index of the last meridian code={% \setColorsForRSurface \tikzmath{% integer \j, \k, \prevk, \prevj, \layerI, \rgbCst, \kini, \kend; if #4 < #5 then {% \kini = int(#4 +1); \kend = #5; } else {% \kini = #4; \kend = int(#5 +1); }; } %% faces \foreach \k [evaluate=\k as \prevk using {int(Mod(\k -1, \NMeridians))}] in {\kini, ..., \kend}{% %\ifnum\k<\NMeridians+1 %\tikzmath{% % \k = int(Mod(\k, \NMeridians)); %} \foreach \j [evaluate=\j as \prevj using int(\j -1)] in {1, ..., \NParallels}{% \tikzmath{% \k = int(Mod(\k, \NMeridians)); if \k==0 then {% \k = \NMeridians; }; \layerI = whatLayer(\ipFTo{\k,\j}, #1, #2); \li = rgbLeftIndex(\ipFTo{\k,\j}, \ipFSun{\k,\j}); \rgbCst = rgbConstant(\ipFTo{\k,\j}, \ipFSun{\k,\j}); } \ifnum \drawWeight{\k,\j} > -1% no negative vertex \begin{pgfonlayer}{\layerI} \path[with L=1, #3] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \else% at least one negative vertex \ifnum \drawWeight{\k,\j} > -5% one negative vertex \oneNegativeVertex{#3}{1}% 1=in light \else% at least two negative vertices \ifnum \drawWeight{\k,\j} > -9 % two negative vertices \twoNegativeVertices{#3}{1} \else% three negative vertices \ifnum \drawWeight{\k,\j} > -13% three negative vertices \threeNegativeVertices{#3}{1} \fi \fi \fi \fi } %\fi } } }, with L/.code={% #1 = 0 no light, #1 = 1 light is on, i.e. for HL \ifnum#1=0 \tikzset{.} \else \tikzset{fill, rgbLeft{\li}!\rgbCst!rgbRight, line width=.01pt} \fi } } \newcommand{\oneNegativeVertex}[2]{% \ifnum \positionH{\prevk,\prevj}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj,1}, \Py{\prevk,\prevj,1}, \Pz{\prevk,\prevj,1}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- (\Px{\prevk,\prevj,2}, \Py{\prevk,\prevj,2}, \Pz{\prevk,\prevj,2}) -- cycle; \end{pgfonlayer} \fi \ifnum \positionH{\k,\prevj}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj,3}, \Py{\k,\prevj,3}, \Pz{\k,\prevj,3}) -- (\Px{\k,\prevj,2}, \Py{\k,\prevj,2}, \Pz{\k,\prevj,2}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \fi \ifnum \positionH{\k,\j}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j,4}, \Py{\k,\j,4}, \Pz{\k,\j,4}) -- (\Px{\k,\j,3}, \Py{\k,\j,3}, \Pz{\k,\j,3}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \fi \ifnum \positionH{\prevk,\j}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j,1}, \Py{\prevk,\j,1}, \Pz{\prevk,\j,1}) -- (\Px{\prevk,\j,4}, \Py{\prevk,\j,4}, \Pz{\prevk,\j,4}) -- cycle; \end{pgfonlayer} \fi } \newcommand{\twoNegativeVertices}[2]{% \ifnum \positionH{\prevk,\prevj}<0% \ifnum \positionH{\k,\prevj}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj,2}, \Py{\prevk,\prevj,2}, \Pz{\prevk,\prevj,2}) -- (\Px{\k,\prevj,2}, \Py{\k,\prevj,2}, \Pz{\k,\prevj,2}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \fi \fi \ifnum \positionH{\k,\prevj}<0% \ifnum \positionH{\k,\j}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj,3}, \Py{\k,\prevj,3}, \Pz{\k,\prevj,3}) -- (\Px{\k,\j,3}, \Py{\k,\j,3}, \Pz{\k,\j,3}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \fi \fi \ifnum \positionH{\k,\j}<0% \ifnum \positionH{\prevk,\j}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j,4}, \Py{\k,\j,4}, \Pz{\k,\j,4}) -- (\Px{\prevk,\j,4}, \Py{\prevk,\j,4}, \Pz{\prevk,\j,4}) -- cycle; \end{pgfonlayer} \fi \fi \ifnum \positionH{\prevk,\j}<0% \ifnum \positionH{\prevk,\prevj}<0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj,1}, \Py{\prevk,\prevj,1}, \Pz{\prevk,\prevj,1}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j,1}, \Py{\prevk,\j,1}, \Pz{\prevk,\j,1}) -- cycle; \end{pgfonlayer} \fi \fi } \newcommand{\threeNegativeVertices}[2]{% \ifnum \positionH{\prevk,\prevj}>0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj}, \Py{\prevk,\prevj}, \Pz{\prevk,\prevj}) -- (\Px{\k,\prevj,3}, \Py{\k,\prevj,3}, \Pz{\k,\prevj,3}) -- (\Px{\prevk,\j,4}, \Py{\prevk,\j,4}, \Pz{\prevk,\j,4}) -- cycle; \end{pgfonlayer} \fi \ifnum \positionH{\k,\prevj}>0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj,1}, \Py{\prevk,\prevj,1}, \Pz{\prevk,\prevj,1}) -- (\Px{\k,\prevj}, \Py{\k,\prevj}, \Pz{\k,\prevj}) -- (\Px{\k,\j,4}, \Py{\k,\j,4}, \Pz{\k,\j,4}) -- cycle; \end{pgfonlayer} \fi \ifnum \positionH{\k,\j}>0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\k,\prevj,2}, \Py{\k,\prevj,2}, \Pz{\k,\prevj,2}) -- (\Px{\k,\j}, \Py{\k,\j}, \Pz{\k,\j}) -- (\Px{\prevk,\j,1}, \Py{\prevk,\j,1}, \Pz{\prevk,\j,1}) -- cycle; \end{pgfonlayer} \fi \ifnum \positionH{\prevk,\j}>0% \begin{pgfonlayer}{\layerI} \path[with L=#2, #1] (\Px{\prevk,\prevj,2}, \Py{\prevk,\prevj,2}, \Pz{\prevk,\prevj,2}) -- (\Px{\k,\j,3}, \Py{\k,\j,3}, \Pz{\k,\j,3}) -- (\Px{\prevk,\j}, \Py{\prevk,\j}, \Pz{\prevk,\j}) -- cycle; \end{pgfonlayer} \fi }