3

The shading of the interp option in 3D surface plots always has vertically shifting gradients.

Is there a way to obtain horizontal gradients?

Example image below, only instead imagine the right side of the sphere to start out white and transition to black on the antipodal point.

enter image description here

\documentclass{article}
\usepackage[a4paper,top=3cm,bottom=3cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\usepgfplotslibrary{patchplots}
\usepgfplotslibrary{colormaps}

\usetikzlibrary{arrows.meta}
\usetikzlibrary{shadings}
\usepackage{xcolor}
\usepackage{tikz-3dplot}

\begin{document}
\begin{tikzpicture}[scale=2]
\begin{axis}[axis equal image, axis lines=center, ticks=none, view/h=120, view/v=20, enlarge x limits={abs=2pt}, enlarge y limits={abs=2pt}, enlarge z limits={abs=2pt}]

    \addplot3+[domain=2:3.65, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({-x},{0},{0});
    \addplot3+[domain=2:2.4, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({0},{-x},{0});
    \addplot3+[domain=2:2.25, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({0},{0},{-x});
%sphere
    \addplot3[surf, shader=interp, colormap={custom}{rgb255=(0,0,0)rgb255=(250,250,250)}, z buffer = sort, samples = 50,
    variable = \u, variable y = \v, domain = 0:180, y domain = 0:360] ({2*cos(u)*sin(v)}, {2*sin(u)*sin(v)}, {2*cos(v)});
%viviani window underlay edge
    \addplot3+[domain=0:4*pi, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
%viviani cylinder parts
    \addplot3[surf, shader=interp, colormap={custom}{rgb255=(100,100,100)rgb255=(255,255,255)}, z buffer = sort, samples = 35, 
    variable = \u, variable y = \v, domain = 0:360, y domain = -2:0, ] ({1+cos(u)}, {sin(u)}, {min(-sqrt(4 - 2*x),v)});
    \addplot3[surf, shader=interp, colormap={custom}{rgb255=(255,255,255)rgb255=(100,100,100)}, z buffer = sort, samples = 35, 
    variable = \u, variable y = \v, domain = 0:360, y domain = 0:2, ] ({1+cos(u)}, {sin(u)}, {max(sqrt(4 - 2*x),v)});
%viviani window overlay edge
    \addplot3+[domain=-pi/3:2*pi/3, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
    \addplot3+[domain=5*pi/3:8*pi/3, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
    \addplot3+[domain=2.34375:4.5325, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
%axis extensions
    \addplot3+[domain=2:3.625, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({x},{0},{0});
    \addplot3+[domain=2:2.4, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({0},{x},{0});
    \addplot3+[domain=2:2.25, samples=5, samples y=0, line width= 0.37pt, no marks, smooth, solid, black]({0},{0},{x});
\end{axis}\end{tikzpicture}
\end{document}
0

1 Answer 1

5

You can adjust the point meta. I introduce an angle \myangle that determines the direction.

\documentclass{article}
\usepackage[a4paper,top=3cm,bottom=3cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\usepgfplotslibrary{colormaps}


\begin{document}
\begin{tikzpicture}[scale=2]
\pgfmathsetmacro{\myangle}{30}
\begin{axis}[axis equal image, axis lines=center, ticks=none, view/h=120, view/v=20, enlarge x limits={abs=2pt}, enlarge y limits={abs=2pt}, enlarge z limits={abs=2pt}]

    \addplot3+[domain=2:3.65, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({-x},{0},{0});
    \addplot3+[domain=2:2.4, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({0},{-x},{0});
    \addplot3+[domain=2:2.25, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({0},{0},{-x});
%sphere
    \addplot3[surf, shader=interp, colormap={custom}{rgb255=(0,0,0)rgb255=(250,250,250)}, z buffer = sort, samples = 50,
    variable = \u, variable y = \v, domain = 0:180, y domain = 0:360] ({2*cos(u)*sin(v)}, {2*sin(u)*sin(v)}, {2*cos(v)});
%viviani window underlay edge
    \addplot3+[domain=0:4*pi, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
%viviani cylinder parts
    \addplot3[surf, shader=interp,point meta={cos(\myangle)*x+sin(\myangle)*y},
    colormap={custom}{rgb255=(255,255,255)rgb255=(100,100,100)}, z buffer = sort, samples = 35, 
    variable = \u, variable y = \v, domain = 0:360, y domain = -2:0, ] ({1+cos(u)}, {sin(u)}, {min(-sqrt(4 - 2*x),v)});
    \addplot3[surf, shader=interp,point meta={cos(\myangle)*x+sin(\myangle)*y},
     colormap={custom}{rgb255=(255,255,255)rgb255=(100,100,100)}, z buffer = sort, samples = 35, 
    variable = \u, variable y = \v, domain = 0:360, y domain = 0:2, ] ({1+cos(u)}, {sin(u)}, {max(sqrt(4 - 2*x),v)});
%viviani window overlay edge
    \addplot3+[domain=-pi/3:2*pi/3, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
    \addplot3+[domain=5*pi/3:8*pi/3, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
    \addplot3+[domain=2.34375:4.5325, samples=50, samples y=0, no marks, smooth, solid, black, thin]({1+cos(deg(x))},{sin(deg(x))},{2*sin(deg(x)/2)});
%axis extensions
    \addplot3+[domain=2:3.625, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({x},{0},{0});
    \addplot3+[domain=2:2.4, samples=5, samples y=0, line width= 0.31pt, no marks, smooth, solid, black]({0},{x},{0});
    \addplot3+[domain=2:2.25, samples=5, samples y=0, line width= 0.37pt, no marks, smooth, solid, black]({0},{0},{x});
\end{axis}\end{tikzpicture}
\end{document}

enter image description here

If you set this angle to 110 you get

enter image description here

2
  • I tried to make different shadings for the two surfaces but it seems that is not possible as they somehow interfere with each other. Do you know how to workaround this? Oct 3, 2019 at 4:43
  • @JackTigerLam Could you please post a new question that has the code that you have tried?
    – user194703
    Oct 3, 2019 at 4:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.