Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- documentclass[tikz,border=3.14mm]{standalone}
- usetikzlibrary{intersections}
- usepackage{pgfplots}
- pgfplotsset{compat=1.16}
- usepgfplotslibrary{fillbetween}
- usepackage{tikz-3dplot}
- pgfkeys{/tikz/.cd,
- hidden opacity/.store in=HiddenOpacity,
- hidden opacity=0.3,
- }
- makeatletter
- % from https://tex.stackexchange.com/a/375604/121799
- %along z axis
- define@key{z sphericalkeys}{radius}{defmyradius{#1}}
- define@key{z sphericalkeys}{theta}{defmytheta{#1}}
- define@key{z sphericalkeys}{phi}{defmyphi{#1}}
- tikzdeclarecoordinatesystem{z spherical}{%
- setkeys{z sphericalkeys}{#1}%
- pgfmathsetmacro{Xtest}{cos(90-tdplotmaintheta)*cos(tdplotmainphi-90)*cos(mytheta)*cos(myphi)
- +cos(90-tdplotmaintheta)*sin(tdplotmainphi-90)*cos(mytheta)*sin(myphi)
- +sin(90-tdplotmaintheta)*sin(mytheta)}
- % Xtest is the projection of the coordinate on the normal vector of the visible plane
- pgfmathsetmacro{ntest}{ifthenelse(Xtest<0,0,1)}
- ifnumntest=0
- xdefMCheatOpa{HiddenOpacity}
- else
- xdefMCheatOpa{1}
- fi
- %typeout{mytheta,tdplotmaintheta;myphi,tdplotmainphi:ntest}
- pgfpointxyz{myradius*cos(mytheta)*cos(myphi)}{%
- myradius*cos(mytheta)*sin(myphi)}{myradius*sin(mytheta)}}
- %%%%%%%%%%%%%%%%%
- % define "new" plot handler
- tikzoption{spherical smooth}[]{lettikz@plot@handler=pgfplothandlersphericalcurveto}
- pgfdeclareplothandler{pgfplothandlersphericalcurveto}{}{%
- point macro=pgf@plot@curveto@handler@spherical@initial,
- jump macro=pgf@plot@smooth@next@spherical@moveto,
- end macro=pgf@plot@curveto@handler@spherical@finish
- }
- defpgf@plot@smooth@next@spherical@moveto{%
- pgf@plot@curveto@handler@spherical@finish%
- globalpgf@plot@startedfalse%
- globalletpgf@plotstreampointpgf@plot@curveto@handler@spherical@initial%
- }
- defpgf@plot@curveto@handler@spherical@initial#1{%
- pgf@process{#1}%
- ifxtikz@textcolorpgfutil@empty%
- else
- pgfsetstrokecolor{tikz@textcolor}
- fi
- pgf@xa=pgf@x%
- pgf@ya=pgf@y%
- pgf@plot@first@action{pgfqpoint{pgf@xa}{pgf@ya}}%
- xdefpgf@plot@curveto@first{noexpandpgfqpoint{thepgf@xa}{thepgf@ya}}%
- globalletpgf@plot@curveto@first@support=pgf@plot@curveto@first%
- globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@second%
- }
- defpgf@plot@curveto@handler@spherical@second#1{%
- pgf@process{#1}%
- xdefpgf@plot@curveto@second{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
- globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@third%
- globalpgf@plot@startedtrue%
- }
- defpgf@plot@curveto@handler@spherical@third#1{%
- pgf@process{#1}%
- xdefpgf@plot@curveto@current{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
- % compute difference vector:
- pgf@xa=pgf@x%
- pgf@ya=pgf@y%
- pgf@process{pgf@plot@curveto@first}
- advancepgf@xa by-pgf@x%
- advancepgf@ya by-pgf@y%
- % compute support directions:
- pgf@xa=pgf@plottensionpgf@xa%
- pgf@ya=pgf@plottensionpgf@ya%
- % first marshal:
- pgf@process{pgf@plot@curveto@second}%
- pgf@xb=pgf@x%
- pgf@yb=pgf@y%
- pgf@xc=pgf@x%
- pgf@yc=pgf@y%
- advancepgf@xb by-pgf@xa%
- advancepgf@yb by-pgf@ya%
- advancepgf@xc bypgf@xa%
- advancepgf@yc bypgf@ya%
- @ifundefined{MCheatOpa}{}{%
- pgf@plotstreamspecial{pgfsetstrokeopacity{MCheatOpa}}}
- edefpgf@marshal{noexpandpgfsetstrokeopacity{noexpandMCheatOpa}
- noexpandpgfpathcurveto{noexpandpgf@plot@curveto@first@support}%
- {noexpandpgfqpoint{thepgf@xb}{thepgf@yb}}{noexpandpgf@plot@curveto@second}
- noexpandpgfusepathqstroke
- noexpandpgfpathmoveto{noexpandpgf@plot@curveto@second}}%
- {pgf@marshal}%
- %pgfusepathqstroke%
- % Prepare next:
- globalletpgf@plot@curveto@first=pgf@plot@curveto@second%
- globalletpgf@plot@curveto@second=pgf@plot@curveto@current%
- xdefpgf@plot@curveto@first@support{noexpandpgfqpoint{thepgf@xc}{thepgf@yc}}%
- }
- defpgf@plot@curveto@handler@spherical@finish{%
- ifpgf@plot@started%
- pgfpathcurveto{pgf@plot@curveto@first@support}{pgf@plot@curveto@second}{pgf@plot@curveto@second}%
- fi%
- }
- makeatother
- begin{document}
- pgfmathsetmacro{RadiusSphere}{3}
- begin{tikzpicture}
- shade[name path=sphere,ball color = gray!40, opacity = 0.5]
- plot[smooth,domain=-180:180] ({RadiusSphere*cos(x)},{RadiusSphere*sin(x)});
- tdplotsetmaincoords{42}{205}
- begin{scope}[tdplot_main_coords,samples=60]
- %
- % draw[-latex,orange] (0,0,0) -- (z spherical cs: radius=RadiusSphere,
- % phi={tdplotmainphi-90},theta={90-tdplotmaintheta});
- % draw[-latex] (0,0,0) -- (RadiusSphere,0,0) node[below]{$x$};
- % draw[-latex] (0,0,0) -- (0,RadiusSphere,0) node[left]{$y$};
- % draw[-latex] (0,0,0) -- (0,0,RadiusSphere) node[left]{$z$};
- draw plot[spherical smooth,variable=x,domain=-180:180]
- (z spherical cs: radius=RadiusSphere,phi={50*sin(x)},theta={40*cos(x)});
- % I modified the plot handler in order to change the opacity along the paths
- % therefore I need to redraw it if I want to use it in fills :-(
- path[name path=circle,fill=blue,opacity=0.2] plot[smooth,variable=x,domain=-180:180]
- (z spherical cs: radius=RadiusSphere,phi={50*sin(x)},theta={40*cos(x)});
- % main technical challenge: TikZ finds tons of intersections instead of 2
- % draw[red, name intersections={of=sphere and circle,name=i, total=t}]
- % foreach s in {1,...,t}{node[fill,circle,scale=0.3,label=above:s] at (i-s) {}}
- % pgfextra{typeout{t}};
- %
- path [%draw,yellow,ultra thick,opacity=1,
- fill=blue,opacity=0.4,
- name path=visible surface,
- intersection segments={
- of=circle and sphere,
- sequence={A5--B0[reverse]--B7[reverse]}
- }];
- end{scope}
- end{tikzpicture}
- end{document}
- shade[name path=sphere,ball color = gray!40, opacity = 0.5]
- plot[smooth,domain=-180:180,samples=120] ({RadiusSphere*cos(x)},{RadiusSphere*sin(x)}); % now 120 samples
- tdplotsetmaincoords{52}{200}
- path [%draw,yellow,ultra thick,opacity=1,
- fill=blue,opacity=0.4,
- name path=visible surface,
- intersection segments={
- of=circle and sphere,
- sequence={A4--B0[reverse]--B5[reverse]}
- }];
- documentclass[tikz,border=3.14mm]{standalone}
- usetikzlibrary{intersections,decorations.markings}
- usepackage{tikz-3dplot}
- tikzset{endmark/.style={postaction={decorate,decoration={markings,
- mark=at position 0 with {coordinate (X0); },
- mark=at position 1 with {coordinate (X1); }}}}}
- pgfkeys{/tikz/.cd,
- hidden opacity/.store in=HiddenOpacity,
- hidden opacity=0.3,
- }
- makeatletter
- xdefprevhidden@toggle{0}
- xdefspherical@plot@start{0}
- % the spherical coordinates are from https://tex.stackexchange.com/a/375604/121799
- % but the routine got modified to
- % (i) decide whether a point is "visible" or "hidden"
- % (ii)
- %along z axis
- define@key{z sphericalkeys}{radius}{defmyradius{#1}}
- define@key{z sphericalkeys}{theta}{defmytheta{#1}}
- define@key{z sphericalkeys}{phi}{defmyphi{#1}}
- tikzdeclarecoordinatesystem{z spherical}{%
- setkeys{z sphericalkeys}{#1}%
- pgfmathsetmacro{Xtest}{cos(90-tdplotmaintheta)*cos(tdplotmainphi-90)*cos(mytheta)*cos(myphi)
- +cos(90-tdplotmaintheta)*sin(tdplotmainphi-90)*cos(mytheta)*sin(myphi)
- +sin(90-tdplotmaintheta)*sin(mytheta)}
- % Xtest is the projection of the coordinate on the normal vector of the visible plane
- pgfmathsetmacro{ntest}{ifthenelse(Xtest<0,0,1)}
- ifnumntest=0
- xdefMCheatOpa{HiddenOpacity}
- %typeout{pointspace hidden}
- ifnumprevhidden@toggle=1 % previous point was also hidden
- xdefhid@path{hid@path (z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
- else % finish visible path
- ifnumspherical@plot@start=1 % this is the first point of the plot
- %typeout{start}
- else
- ifnumthevis@paths=0
- xdeflst@vis@paths{{vis@path}}
- else
- xdeflst@vis@paths{lst@vis@paths,{vis@path}}
- fi
- stepcounter{vis@paths}
- fi % and start a new hidden path
- xdefhid@path{(z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
- fi
- xdefprevhidden@toggle{1}
- else
- xdefMCheatOpa{1}
- %typeout{pointspace visible}
- ifnumprevhidden@toggle=0 % previous point was also visible
- xdefvis@path{vis@path (z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
- else % finish hidden path
- ifnumspherical@plot@start=1
- %typeout{start}
- else
- ifnumthehid@paths=0
- xdeflst@hid@paths{{hid@path}}
- else
- xdeflst@hid@paths{lst@hid@paths,{hid@path}}
- fi
- stepcounter{hid@paths}
- fi % and start a new visible path
- xdefvis@path{(z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
- fi
- xdefprevhidden@toggle{0}
- fi
- %typeout{mytheta,tdplotmaintheta;myphi,tdplotmainphi:ntest}
- pgfpointxyz{myradius*cos(mytheta)*cos(myphi)}{%
- myradius*cos(mytheta)*sin(myphi)}{myradius*sin(mytheta)}}
- %%%%%%%%%%%%%%%%%
- % define "new" plot handler
- newcounter{vis@paths}
- newcounter{hid@paths}
- tikzoption{spherical smooth}[]{xdeflst@vis@paths{}
- xdeflst@hid@paths{}
- xdefhid@path{}
- xdefvis@path{}
- lettikz@plot@handler=pgfplothandlersphericalcurveto}
- pgfdeclareplothandler{pgfplothandlersphericalcurveto}{}{%
- point macro=pgf@plot@curveto@handler@spherical@initial,
- jump macro=pgf@plot@smooth@next@spherical@moveto,
- end macro=pgf@plot@curveto@handler@spherical@finish
- }
- defpgf@plot@smooth@next@spherical@moveto{%
- pgf@plot@curveto@handler@spherical@finish%
- globalpgf@plot@startedfalse%
- globalletpgf@plotstreampointpgf@plot@curveto@handler@spherical@initial%
- }
- defpgf@plot@curveto@handler@spherical@initial#1{%
- pgf@process{#1}%
- ifxtikz@textcolorpgfutil@empty%
- else
- pgfsetstrokecolor{tikz@textcolor}
- fi
- setcounter{vis@paths}{0}
- setcounter{hid@paths}{0}
- xdefspherical@plot@start{1}
- pgf@xa=pgf@x%
- pgf@ya=pgf@y%
- pgf@plot@first@action{pgfqpoint{pgf@xa}{pgf@ya}}%
- xdefpgf@plot@curveto@first{noexpandpgfqpoint{thepgf@xa}{thepgf@ya}}%
- globalletpgf@plot@curveto@first@support=pgf@plot@curveto@first%
- globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@second%
- }
- defpgf@plot@curveto@handler@spherical@second#1{%
- xdefspherical@plot@start{0}
- pgf@process{#1}%
- xdefpgf@plot@curveto@second{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
- globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@third%
- globalpgf@plot@startedtrue%
- }
- defpgf@plot@curveto@handler@spherical@third#1{%
- pgf@process{#1}%
- xdefpgf@plot@curveto@current{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
- % compute difference vector:
- pgf@xa=pgf@x%
- pgf@ya=pgf@y%
- pgf@process{pgf@plot@curveto@first}
- advancepgf@xa by-pgf@x%
- advancepgf@ya by-pgf@y%
- % compute support directions:
- pgf@xa=pgf@plottensionpgf@xa%
- pgf@ya=pgf@plottensionpgf@ya%
- % first marshal:
- pgf@process{pgf@plot@curveto@second}%
- pgf@xb=pgf@x%
- pgf@yb=pgf@y%
- pgf@xc=pgf@x%
- pgf@yc=pgf@y%
- advancepgf@xb by-pgf@xa%
- advancepgf@yb by-pgf@ya%
- advancepgf@xc bypgf@xa%
- advancepgf@yc bypgf@ya%
- edefpgf@marshal{noexpandpgfsetstrokeopacity{noexpandMCheatOpa}
- noexpandpgfpathcurveto{noexpandpgf@plot@curveto@first@support}%
- {noexpandpgfqpoint{thepgf@xb}{thepgf@yb}}{noexpandpgf@plot@curveto@second}
- noexpandpgfusepathqstroke
- noexpandpgfpathmoveto{noexpandpgf@plot@curveto@second}}%
- {pgf@marshal}%
- %pgfusepathqstroke%
- % Prepare next:
- globalletpgf@plot@curveto@first=pgf@plot@curveto@second%
- globalletpgf@plot@curveto@second=pgf@plot@curveto@current%
- xdefpgf@plot@curveto@first@support{noexpandpgfqpoint{thepgf@xc}{thepgf@yc}}%
- }
- defpgf@plot@curveto@handler@spherical@finish{%
- ifpgf@plot@started%
- pgfpathcurveto{pgf@plot@curveto@first@support}{pgf@plot@curveto@second}{pgf@plot@curveto@second}%
- fi%
- ifnumprevhidden@toggle=1
- xdeflstvispaths{lst@vis@paths}
- ifxhid@pathempty
- else
- %typeout{closingspace hidden}
- ifxlst@hid@pathsempty
- xdeflst@hid@paths{{hid@path}}
- else
- xdeflst@hid@paths{lst@hid@paths,{hid@path}}
- fi
- foreach X [count=Y] in lst@hid@paths
- {xdefmy@len{Y}}
- %typeout{my@lenspace hiddenspace patches}
- xdeflsthidpaths{}
- foreach X [count=Y] in lst@hid@paths
- {ifnumY=1 % save the first stretch
- xdeftmppath{X}
- ifnummy@len=1
- xdeflsthidpaths{{X}}
- fi
- else
- ifnumY=my@len
- ifnumY=2
- xdeflsthidpaths{{Xtmppath}}
- else
- xdeflsthidpaths{lsthidpaths,{Xtmppath}}
- fi
- %typeout{adding:{tmppathX}}
- %typeout{result:lsthidpaths}
- else
- xdeflsthidpaths{lsthidpaths,{X}}
- fi
- fi}
- %typeout{hiddenspace paths:lst@hid@paths}
- fi
- else
- xdeflsthidpaths{lst@hid@paths}
- ifxvis@pathempty
- else
- %typeout{closingspace visible}
- xdeflst@vis@paths{lst@vis@paths,{vis@path}}
- foreach X [count=Y] in lst@vis@paths
- {xdefmy@len{Y}}
- %typeout{my@lenspace hiddenspace coordinates:vis@path}
- xdeflstvispaths{}
- foreach X [count=Y] in lst@vis@paths
- {ifnumY=1 % save the first stretch
- xdeftmppath{X}
- ifnummy@len=1
- xdeflstvispaths{{X}}
- fi
- else
- ifnumY=my@len
- ifnummy@len=1
- xdeflstvispaths{{X}}
- else
- ifnumY=2
- xdeflstvispaths{{Xtmppath}}
- else
- xdeflstvispaths{lstvispaths,{Xtmppath}}
- fi
- %typeout{adding:{tmppathX}}
- %typeout{result:lstvispaths}
- fi
- else
- xdeflstvispaths{lstvispaths,{X}}
- fi
- fi}
- fi
- fi
- }
- makeatother
- newcommand{FillVisibleSurfaces}[1][]{xdefnumvis{0}
- foreach X [count=Y] in lstvispaths
- {ifxXempty
- else
- xdefnumvis{Y}
- fi}
- ifnumnumvis=0%
- else
- foreach X [count=Y] in lstvispaths
- {%typeout{processingspace X}
- path[endmark] plot[tdplot_main_coords,samples=60] coordinates {X};
- fill[#1] let
- p1=(X0),p2=(X1),n1={mod(atan2(y1,x1)+720,360)},n2={mod(atan2(y2,x2)+720,360)}
- in % pgfextra{typeout{visible:space start:n1,end:n2}}
- plot[tdplot_main_coords,samples=60] coordinates {X} -- (X1) arc(n2:n1:RadiusSphere);
- }
- fi
- }
- newcommand{FillHiddenSurfaces}[1][]{xdefnumhid{0}
- foreach X [count=Y] in lsthidpaths
- {ifxXempty
- else
- xdefnumhid{Y}
- fi}
- ifnumnumhid=0%
- else
- foreach X [count=Y] in lsthidpaths
- {
- path[endmark] plot[tdplot_main_coords,samples=60] coordinates {X};
- fill[#1] let
- p1=(X0),p2=(X1),n1={mod(atan2(y1,x1)+720,360)},n2={mod(atan2(y2,x2)+720,360)}
- in %pgfextra{typeout{hiddenspace start:n1,end:n2}}
- plot[tdplot_main_coords,samples=60] coordinates {X} -- (X1) arc(n2:n1:RadiusSphere)
- --cycle;
- }
- fi
- }
- begin{document}
- pgfmathsetmacro{RadiusSphere}{3}
- foreach X in {0,10,...,350}
- {begin{tikzpicture}
- shade[name path=sphere,ball color = gray!40, opacity = 0.5]
- plot[smooth,domain=-180:180,samples=120] ({RadiusSphere*cos(x)},{RadiusSphere*sin(x)});
- tdplotsetmaincoords{110}{X}
- begin{scope}[tdplot_main_coords,samples=60]
- %
- % draw[-latex,orange] (0,0,0) -- (z spherical cs: radius=RadiusSphere,
- % phi={tdplotmainphi-90},theta={90-tdplotmaintheta});
- % draw[-latex] (0,0,0) -- (RadiusSphere,0,0) node[below]{$x$};
- % draw[-latex] (0,0,0) -- (0,RadiusSphere,0) node[left]{$y$};
- % draw[-latex] (0,0,0) -- (0,0,RadiusSphere) node[left]{$z$};
- draw plot[spherical smooth,variable=x,domain=-180:180]
- (z spherical cs: radius=RadiusSphere,phi={50*sin(x)},theta={40*cos(x)});
- end{scope}
- % note that these commands need to be placed *outside* the tdplot_main_coords scope
- FillHiddenSurfaces[blue,opacity=0.2]
- FillVisibleSurfaces[blue,opacity=0.5]
- end{tikzpicture}
- }
- end{document}
Add Comment
Please, Sign In to add comment