Guest User

Untitled

a guest
Jun 22nd, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.12 KB | None | 0 0
  1. documentclass[tikz,border=3.14mm]{standalone}
  2. usetikzlibrary{intersections}
  3. usepackage{pgfplots}
  4. pgfplotsset{compat=1.16}
  5. usepgfplotslibrary{fillbetween}
  6. usepackage{tikz-3dplot}
  7.  
  8. pgfkeys{/tikz/.cd,
  9. hidden opacity/.store in=HiddenOpacity,
  10. hidden opacity=0.3,
  11. }
  12.  
  13. makeatletter
  14.  
  15. % from https://tex.stackexchange.com/a/375604/121799
  16.  
  17. %along z axis
  18. define@key{z sphericalkeys}{radius}{defmyradius{#1}}
  19. define@key{z sphericalkeys}{theta}{defmytheta{#1}}
  20. define@key{z sphericalkeys}{phi}{defmyphi{#1}}
  21. tikzdeclarecoordinatesystem{z spherical}{%
  22. setkeys{z sphericalkeys}{#1}%
  23. pgfmathsetmacro{Xtest}{cos(90-tdplotmaintheta)*cos(tdplotmainphi-90)*cos(mytheta)*cos(myphi)
  24. +cos(90-tdplotmaintheta)*sin(tdplotmainphi-90)*cos(mytheta)*sin(myphi)
  25. +sin(90-tdplotmaintheta)*sin(mytheta)}
  26. % Xtest is the projection of the coordinate on the normal vector of the visible plane
  27. pgfmathsetmacro{ntest}{ifthenelse(Xtest<0,0,1)}
  28. ifnumntest=0
  29. xdefMCheatOpa{HiddenOpacity}
  30. else
  31. xdefMCheatOpa{1}
  32. fi
  33. %typeout{mytheta,tdplotmaintheta;myphi,tdplotmainphi:ntest}
  34. pgfpointxyz{myradius*cos(mytheta)*cos(myphi)}{%
  35. myradius*cos(mytheta)*sin(myphi)}{myradius*sin(mytheta)}}
  36.  
  37. %%%%%%%%%%%%%%%%%
  38. % define "new" plot handler
  39. tikzoption{spherical smooth}[]{lettikz@plot@handler=pgfplothandlersphericalcurveto}
  40.  
  41.  
  42. pgfdeclareplothandler{pgfplothandlersphericalcurveto}{}{%
  43. point macro=pgf@plot@curveto@handler@spherical@initial,
  44. jump macro=pgf@plot@smooth@next@spherical@moveto,
  45. end macro=pgf@plot@curveto@handler@spherical@finish
  46. }
  47.  
  48. defpgf@plot@smooth@next@spherical@moveto{%
  49. pgf@plot@curveto@handler@spherical@finish%
  50. globalpgf@plot@startedfalse%
  51. globalletpgf@plotstreampointpgf@plot@curveto@handler@spherical@initial%
  52. }
  53.  
  54. defpgf@plot@curveto@handler@spherical@initial#1{%
  55. pgf@process{#1}%
  56. ifxtikz@textcolorpgfutil@empty%
  57. else
  58. pgfsetstrokecolor{tikz@textcolor}
  59. fi
  60. pgf@xa=pgf@x%
  61. pgf@ya=pgf@y%
  62. pgf@plot@first@action{pgfqpoint{pgf@xa}{pgf@ya}}%
  63. xdefpgf@plot@curveto@first{noexpandpgfqpoint{thepgf@xa}{thepgf@ya}}%
  64. globalletpgf@plot@curveto@first@support=pgf@plot@curveto@first%
  65. globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@second%
  66. }
  67.  
  68. defpgf@plot@curveto@handler@spherical@second#1{%
  69. pgf@process{#1}%
  70. xdefpgf@plot@curveto@second{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
  71. globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@third%
  72. globalpgf@plot@startedtrue%
  73. }
  74.  
  75. defpgf@plot@curveto@handler@spherical@third#1{%
  76. pgf@process{#1}%
  77. xdefpgf@plot@curveto@current{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
  78. % compute difference vector:
  79. pgf@xa=pgf@x%
  80. pgf@ya=pgf@y%
  81. pgf@process{pgf@plot@curveto@first}
  82. advancepgf@xa by-pgf@x%
  83. advancepgf@ya by-pgf@y%
  84. % compute support directions:
  85. pgf@xa=pgf@plottensionpgf@xa%
  86. pgf@ya=pgf@plottensionpgf@ya%
  87. % first marshal:
  88. pgf@process{pgf@plot@curveto@second}%
  89. pgf@xb=pgf@x%
  90. pgf@yb=pgf@y%
  91. pgf@xc=pgf@x%
  92. pgf@yc=pgf@y%
  93. advancepgf@xb by-pgf@xa%
  94. advancepgf@yb by-pgf@ya%
  95. advancepgf@xc bypgf@xa%
  96. advancepgf@yc bypgf@ya%
  97. @ifundefined{MCheatOpa}{}{%
  98. pgf@plotstreamspecial{pgfsetstrokeopacity{MCheatOpa}}}
  99. edefpgf@marshal{noexpandpgfsetstrokeopacity{noexpandMCheatOpa}
  100. noexpandpgfpathcurveto{noexpandpgf@plot@curveto@first@support}%
  101. {noexpandpgfqpoint{thepgf@xb}{thepgf@yb}}{noexpandpgf@plot@curveto@second}
  102. noexpandpgfusepathqstroke
  103. noexpandpgfpathmoveto{noexpandpgf@plot@curveto@second}}%
  104. {pgf@marshal}%
  105. %pgfusepathqstroke%
  106. % Prepare next:
  107. globalletpgf@plot@curveto@first=pgf@plot@curveto@second%
  108. globalletpgf@plot@curveto@second=pgf@plot@curveto@current%
  109. xdefpgf@plot@curveto@first@support{noexpandpgfqpoint{thepgf@xc}{thepgf@yc}}%
  110. }
  111.  
  112. defpgf@plot@curveto@handler@spherical@finish{%
  113. ifpgf@plot@started%
  114. pgfpathcurveto{pgf@plot@curveto@first@support}{pgf@plot@curveto@second}{pgf@plot@curveto@second}%
  115. fi%
  116. }
  117. makeatother
  118.  
  119.  
  120. begin{document}
  121. pgfmathsetmacro{RadiusSphere}{3}
  122.  
  123.  
  124. begin{tikzpicture}
  125. shade[name path=sphere,ball color = gray!40, opacity = 0.5]
  126. plot[smooth,domain=-180:180] ({RadiusSphere*cos(x)},{RadiusSphere*sin(x)});
  127.  
  128.  
  129. tdplotsetmaincoords{42}{205}
  130. begin{scope}[tdplot_main_coords,samples=60]
  131. %
  132. % draw[-latex,orange] (0,0,0) -- (z spherical cs: radius=RadiusSphere,
  133. % phi={tdplotmainphi-90},theta={90-tdplotmaintheta});
  134. % draw[-latex] (0,0,0) -- (RadiusSphere,0,0) node[below]{$x$};
  135. % draw[-latex] (0,0,0) -- (0,RadiusSphere,0) node[left]{$y$};
  136. % draw[-latex] (0,0,0) -- (0,0,RadiusSphere) node[left]{$z$};
  137.  
  138. draw plot[spherical smooth,variable=x,domain=-180:180]
  139. (z spherical cs: radius=RadiusSphere,phi={50*sin(x)},theta={40*cos(x)});
  140. % I modified the plot handler in order to change the opacity along the paths
  141. % therefore I need to redraw it if I want to use it in fills :-(
  142. path[name path=circle,fill=blue,opacity=0.2] plot[smooth,variable=x,domain=-180:180]
  143. (z spherical cs: radius=RadiusSphere,phi={50*sin(x)},theta={40*cos(x)});
  144.  
  145. % main technical challenge: TikZ finds tons of intersections instead of 2
  146. % draw[red, name intersections={of=sphere and circle,name=i, total=t}]
  147. % foreach s in {1,...,t}{node[fill,circle,scale=0.3,label=above:s] at (i-s) {}}
  148. % pgfextra{typeout{t}};
  149.  
  150. %
  151. path [%draw,yellow,ultra thick,opacity=1,
  152. fill=blue,opacity=0.4,
  153. name path=visible surface,
  154. intersection segments={
  155. of=circle and sphere,
  156. sequence={A5--B0[reverse]--B7[reverse]}
  157. }];
  158.  
  159. end{scope}
  160. end{tikzpicture}
  161. end{document}
  162.  
  163. shade[name path=sphere,ball color = gray!40, opacity = 0.5]
  164. plot[smooth,domain=-180:180,samples=120] ({RadiusSphere*cos(x)},{RadiusSphere*sin(x)}); % now 120 samples
  165. tdplotsetmaincoords{52}{200}
  166.  
  167. path [%draw,yellow,ultra thick,opacity=1,
  168. fill=blue,opacity=0.4,
  169. name path=visible surface,
  170. intersection segments={
  171. of=circle and sphere,
  172. sequence={A4--B0[reverse]--B5[reverse]}
  173. }];
  174.  
  175. documentclass[tikz,border=3.14mm]{standalone}
  176. usetikzlibrary{intersections,decorations.markings}
  177. usepackage{tikz-3dplot}
  178. tikzset{endmark/.style={postaction={decorate,decoration={markings,
  179. mark=at position 0 with {coordinate (X0); },
  180. mark=at position 1 with {coordinate (X1); }}}}}
  181.  
  182. pgfkeys{/tikz/.cd,
  183. hidden opacity/.store in=HiddenOpacity,
  184. hidden opacity=0.3,
  185. }
  186.  
  187. makeatletter
  188.  
  189. xdefprevhidden@toggle{0}
  190. xdefspherical@plot@start{0}
  191. % the spherical coordinates are from https://tex.stackexchange.com/a/375604/121799
  192. % but the routine got modified to
  193. % (i) decide whether a point is "visible" or "hidden"
  194. % (ii)
  195.  
  196. %along z axis
  197. define@key{z sphericalkeys}{radius}{defmyradius{#1}}
  198. define@key{z sphericalkeys}{theta}{defmytheta{#1}}
  199. define@key{z sphericalkeys}{phi}{defmyphi{#1}}
  200. tikzdeclarecoordinatesystem{z spherical}{%
  201. setkeys{z sphericalkeys}{#1}%
  202. pgfmathsetmacro{Xtest}{cos(90-tdplotmaintheta)*cos(tdplotmainphi-90)*cos(mytheta)*cos(myphi)
  203. +cos(90-tdplotmaintheta)*sin(tdplotmainphi-90)*cos(mytheta)*sin(myphi)
  204. +sin(90-tdplotmaintheta)*sin(mytheta)}
  205. % Xtest is the projection of the coordinate on the normal vector of the visible plane
  206. pgfmathsetmacro{ntest}{ifthenelse(Xtest<0,0,1)}
  207. ifnumntest=0
  208. xdefMCheatOpa{HiddenOpacity}
  209. %typeout{pointspace hidden}
  210. ifnumprevhidden@toggle=1 % previous point was also hidden
  211. xdefhid@path{hid@path (z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
  212. else % finish visible path
  213. ifnumspherical@plot@start=1 % this is the first point of the plot
  214. %typeout{start}
  215. else
  216. ifnumthevis@paths=0
  217. xdeflst@vis@paths{{vis@path}}
  218. else
  219. xdeflst@vis@paths{lst@vis@paths,{vis@path}}
  220. fi
  221. stepcounter{vis@paths}
  222. fi % and start a new hidden path
  223. xdefhid@path{(z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
  224. fi
  225. xdefprevhidden@toggle{1}
  226. else
  227. xdefMCheatOpa{1}
  228. %typeout{pointspace visible}
  229. ifnumprevhidden@toggle=0 % previous point was also visible
  230. xdefvis@path{vis@path (z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
  231. else % finish hidden path
  232. ifnumspherical@plot@start=1
  233. %typeout{start}
  234. else
  235. ifnumthehid@paths=0
  236. xdeflst@hid@paths{{hid@path}}
  237. else
  238. xdeflst@hid@paths{lst@hid@paths,{hid@path}}
  239. fi
  240. stepcounter{hid@paths}
  241. fi % and start a new visible path
  242. xdefvis@path{(z spherical cs: radius={myradius},phi={myphi},theta={mytheta})}
  243. fi
  244. xdefprevhidden@toggle{0}
  245. fi
  246. %typeout{mytheta,tdplotmaintheta;myphi,tdplotmainphi:ntest}
  247. pgfpointxyz{myradius*cos(mytheta)*cos(myphi)}{%
  248. myradius*cos(mytheta)*sin(myphi)}{myradius*sin(mytheta)}}
  249.  
  250. %%%%%%%%%%%%%%%%%
  251. % define "new" plot handler
  252. newcounter{vis@paths}
  253. newcounter{hid@paths}
  254. tikzoption{spherical smooth}[]{xdeflst@vis@paths{}
  255. xdeflst@hid@paths{}
  256. xdefhid@path{}
  257. xdefvis@path{}
  258. lettikz@plot@handler=pgfplothandlersphericalcurveto}
  259.  
  260.  
  261. pgfdeclareplothandler{pgfplothandlersphericalcurveto}{}{%
  262. point macro=pgf@plot@curveto@handler@spherical@initial,
  263. jump macro=pgf@plot@smooth@next@spherical@moveto,
  264. end macro=pgf@plot@curveto@handler@spherical@finish
  265. }
  266.  
  267. defpgf@plot@smooth@next@spherical@moveto{%
  268. pgf@plot@curveto@handler@spherical@finish%
  269. globalpgf@plot@startedfalse%
  270. globalletpgf@plotstreampointpgf@plot@curveto@handler@spherical@initial%
  271. }
  272.  
  273. defpgf@plot@curveto@handler@spherical@initial#1{%
  274. pgf@process{#1}%
  275. ifxtikz@textcolorpgfutil@empty%
  276. else
  277. pgfsetstrokecolor{tikz@textcolor}
  278. fi
  279. setcounter{vis@paths}{0}
  280. setcounter{hid@paths}{0}
  281. xdefspherical@plot@start{1}
  282. pgf@xa=pgf@x%
  283. pgf@ya=pgf@y%
  284. pgf@plot@first@action{pgfqpoint{pgf@xa}{pgf@ya}}%
  285. xdefpgf@plot@curveto@first{noexpandpgfqpoint{thepgf@xa}{thepgf@ya}}%
  286. globalletpgf@plot@curveto@first@support=pgf@plot@curveto@first%
  287. globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@second%
  288. }
  289.  
  290. defpgf@plot@curveto@handler@spherical@second#1{%
  291. xdefspherical@plot@start{0}
  292. pgf@process{#1}%
  293. xdefpgf@plot@curveto@second{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
  294. globalletpgf@plotstreampoint=pgf@plot@curveto@handler@spherical@third%
  295. globalpgf@plot@startedtrue%
  296. }
  297.  
  298. defpgf@plot@curveto@handler@spherical@third#1{%
  299. pgf@process{#1}%
  300. xdefpgf@plot@curveto@current{noexpandpgfqpoint{thepgf@x}{thepgf@y}}%
  301. % compute difference vector:
  302. pgf@xa=pgf@x%
  303. pgf@ya=pgf@y%
  304. pgf@process{pgf@plot@curveto@first}
  305. advancepgf@xa by-pgf@x%
  306. advancepgf@ya by-pgf@y%
  307. % compute support directions:
  308. pgf@xa=pgf@plottensionpgf@xa%
  309. pgf@ya=pgf@plottensionpgf@ya%
  310. % first marshal:
  311. pgf@process{pgf@plot@curveto@second}%
  312. pgf@xb=pgf@x%
  313. pgf@yb=pgf@y%
  314. pgf@xc=pgf@x%
  315. pgf@yc=pgf@y%
  316. advancepgf@xb by-pgf@xa%
  317. advancepgf@yb by-pgf@ya%
  318. advancepgf@xc bypgf@xa%
  319. advancepgf@yc bypgf@ya%
  320. edefpgf@marshal{noexpandpgfsetstrokeopacity{noexpandMCheatOpa}
  321. noexpandpgfpathcurveto{noexpandpgf@plot@curveto@first@support}%
  322. {noexpandpgfqpoint{thepgf@xb}{thepgf@yb}}{noexpandpgf@plot@curveto@second}
  323. noexpandpgfusepathqstroke
  324. noexpandpgfpathmoveto{noexpandpgf@plot@curveto@second}}%
  325. {pgf@marshal}%
  326. %pgfusepathqstroke%
  327. % Prepare next:
  328. globalletpgf@plot@curveto@first=pgf@plot@curveto@second%
  329. globalletpgf@plot@curveto@second=pgf@plot@curveto@current%
  330. xdefpgf@plot@curveto@first@support{noexpandpgfqpoint{thepgf@xc}{thepgf@yc}}%
  331. }
  332.  
  333. defpgf@plot@curveto@handler@spherical@finish{%
  334. ifpgf@plot@started%
  335. pgfpathcurveto{pgf@plot@curveto@first@support}{pgf@plot@curveto@second}{pgf@plot@curveto@second}%
  336. fi%
  337. ifnumprevhidden@toggle=1
  338. xdeflstvispaths{lst@vis@paths}
  339. ifxhid@pathempty
  340. else
  341. %typeout{closingspace hidden}
  342. ifxlst@hid@pathsempty
  343. xdeflst@hid@paths{{hid@path}}
  344. else
  345. xdeflst@hid@paths{lst@hid@paths,{hid@path}}
  346. fi
  347. foreach X [count=Y] in lst@hid@paths
  348. {xdefmy@len{Y}}
  349. %typeout{my@lenspace hiddenspace patches}
  350. xdeflsthidpaths{}
  351. foreach X [count=Y] in lst@hid@paths
  352. {ifnumY=1 % save the first stretch
  353. xdeftmppath{X}
  354. ifnummy@len=1
  355. xdeflsthidpaths{{X}}
  356. fi
  357. else
  358. ifnumY=my@len
  359. ifnumY=2
  360. xdeflsthidpaths{{Xtmppath}}
  361. else
  362. xdeflsthidpaths{lsthidpaths,{Xtmppath}}
  363. fi
  364. %typeout{adding:{tmppathX}}
  365. %typeout{result:lsthidpaths}
  366. else
  367. xdeflsthidpaths{lsthidpaths,{X}}
  368. fi
  369. fi}
  370. %typeout{hiddenspace paths:lst@hid@paths}
  371. fi
  372. else
  373. xdeflsthidpaths{lst@hid@paths}
  374. ifxvis@pathempty
  375. else
  376. %typeout{closingspace visible}
  377. xdeflst@vis@paths{lst@vis@paths,{vis@path}}
  378. foreach X [count=Y] in lst@vis@paths
  379. {xdefmy@len{Y}}
  380. %typeout{my@lenspace hiddenspace coordinates:vis@path}
  381. xdeflstvispaths{}
  382. foreach X [count=Y] in lst@vis@paths
  383. {ifnumY=1 % save the first stretch
  384. xdeftmppath{X}
  385. ifnummy@len=1
  386. xdeflstvispaths{{X}}
  387. fi
  388. else
  389. ifnumY=my@len
  390. ifnummy@len=1
  391. xdeflstvispaths{{X}}
  392. else
  393. ifnumY=2
  394. xdeflstvispaths{{Xtmppath}}
  395. else
  396. xdeflstvispaths{lstvispaths,{Xtmppath}}
  397. fi
  398. %typeout{adding:{tmppathX}}
  399. %typeout{result:lstvispaths}
  400. fi
  401. else
  402. xdeflstvispaths{lstvispaths,{X}}
  403. fi
  404. fi}
  405. fi
  406. fi
  407. }
  408. makeatother
  409.  
  410. newcommand{FillVisibleSurfaces}[1][]{xdefnumvis{0}
  411. foreach X [count=Y] in lstvispaths
  412. {ifxXempty
  413. else
  414. xdefnumvis{Y}
  415. fi}
  416. ifnumnumvis=0%
  417. else
  418. foreach X [count=Y] in lstvispaths
  419. {%typeout{processingspace X}
  420. path[endmark] plot[tdplot_main_coords,samples=60] coordinates {X};
  421. fill[#1] let
  422. p1=(X0),p2=(X1),n1={mod(atan2(y1,x1)+720,360)},n2={mod(atan2(y2,x2)+720,360)}
  423. in % pgfextra{typeout{visible:space start:n1,end:n2}}
  424. plot[tdplot_main_coords,samples=60] coordinates {X} -- (X1) arc(n2:n1:RadiusSphere);
  425. }
  426. fi
  427. }
  428. newcommand{FillHiddenSurfaces}[1][]{xdefnumhid{0}
  429. foreach X [count=Y] in lsthidpaths
  430. {ifxXempty
  431. else
  432. xdefnumhid{Y}
  433. fi}
  434. ifnumnumhid=0%
  435. else
  436. foreach X [count=Y] in lsthidpaths
  437. {
  438. path[endmark] plot[tdplot_main_coords,samples=60] coordinates {X};
  439. fill[#1] let
  440. p1=(X0),p2=(X1),n1={mod(atan2(y1,x1)+720,360)},n2={mod(atan2(y2,x2)+720,360)}
  441. in %pgfextra{typeout{hiddenspace start:n1,end:n2}}
  442. plot[tdplot_main_coords,samples=60] coordinates {X} -- (X1) arc(n2:n1:RadiusSphere)
  443. --cycle;
  444. }
  445. fi
  446. }
  447.  
  448.  
  449. begin{document}
  450. pgfmathsetmacro{RadiusSphere}{3}
  451.  
  452. foreach X in {0,10,...,350}
  453. {begin{tikzpicture}
  454. shade[name path=sphere,ball color = gray!40, opacity = 0.5]
  455. plot[smooth,domain=-180:180,samples=120] ({RadiusSphere*cos(x)},{RadiusSphere*sin(x)});
  456.  
  457.  
  458. tdplotsetmaincoords{110}{X}
  459. begin{scope}[tdplot_main_coords,samples=60]
  460. %
  461. % draw[-latex,orange] (0,0,0) -- (z spherical cs: radius=RadiusSphere,
  462. % phi={tdplotmainphi-90},theta={90-tdplotmaintheta});
  463. % draw[-latex] (0,0,0) -- (RadiusSphere,0,0) node[below]{$x$};
  464. % draw[-latex] (0,0,0) -- (0,RadiusSphere,0) node[left]{$y$};
  465. % draw[-latex] (0,0,0) -- (0,0,RadiusSphere) node[left]{$z$};
  466.  
  467. draw plot[spherical smooth,variable=x,domain=-180:180]
  468. (z spherical cs: radius=RadiusSphere,phi={50*sin(x)},theta={40*cos(x)});
  469. end{scope}
  470. % note that these commands need to be placed *outside* the tdplot_main_coords scope
  471. FillHiddenSurfaces[blue,opacity=0.2]
  472. FillVisibleSurfaces[blue,opacity=0.5]
  473. end{tikzpicture}
  474. }
  475. end{document}
Add Comment
Please, Sign In to add comment