Desenhar plotagens de superfície 3D que se cruzam

Desenhar plotagens de superfície 3D que se cruzam

Estou tentando desenhar seis esferas que se cruzam semitransparentes de cores diferentes - duas em cada eixo x, y, z e todas unidas na origem - como mostrado na figura abaixo. Observe como todas as esferas se cruzam.

Resultado (aproximadamente) pretendido

Visto que esta figura é criada em Matlab, tentei converter a figura em pgfplotscódigo, usando matlab2tikz, mas não funcionou. Abaixo está o Matlabcódigo da figura.

Theta=linspace(0,2*pi,200);
Phi=linspace(-pi/2,pi/2,200);
[theta,phi]=meshgrid(Theta,Phi);

rho1=cos(theta).*cos(phi);
rho2=-cos(theta).*cos(phi);
rho3=sin(theta).*cos(phi);
rho4=-sin(theta).*cos(phi);
rho5=sin(phi);
rho6=-sin(phi);

[x1,y1,z1]=sph2cart(theta,phi,rho1);
[x2,y2,z2]=sph2cart(theta,phi,rho2);
[x3,y3,z3]=sph2cart(theta,phi,rho3);
[x4,y4,z4]=sph2cart(theta,phi,rho4);
[x5,y5,z5]=sph2cart(theta,phi,rho5);
[x6,y6,z6]=sph2cart(theta,phi,rho6);

surf(x1,y1,z1,'FaceColor','red','EdgeColor','none')
hold on
surf(x2,y2,z2,'FaceColor','red','EdgeColor','none')
surf(x3,y3,z3,'FaceColor','blue','EdgeColor','none')
surf(x4,y4,z4,'FaceColor','blue','EdgeColor','none')
surf(x5,y5,z5,'FaceColor','green','EdgeColor','none')
surf(x6,y6,z6,'FaceColor','green','EdgeColor','none')

alpha(0.6)
camlight left
lighting flat

Em seguida, tentei desenhar a figura em tikz-3dplote pst-solides3d. Com ambos os métodos, tive o problema de as superfícies não se cruzarem. Em vez disso, projeções bidimensionais das esferas foram desenhadas separadamente na tela, uma sobre a outra, conforme mostrado nas figuras abaixo. A primeira figura é a saída de tikz-3dplote a segunda figura é a saída de pst-solides3d.

Tente com tikz-3dplot Tente com pst-solides3d

Com tikz-3dplot, também tive um problema com certos eixos que pareciam estar no topo das esferas, quando deveriam parecer estar dentro delas (ref. a metade negativa do eixo y).

Abaixo estão os códigos das figuras acima, na mesma ordem.

\documentclass[11pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz,tikz-3dplot}
    \usetikzlibrary{arrows}

\begin{document}

\tdplotsetmaincoords{70}{135}

\begin{tikzpicture}[tdplot_main_coords,fill  opacity=.5,>=latex]
\pgfsetlinewidth{.1pt}

\tdplotsphericalsurfaceplot{72}{36}{4*abs(cos(\tdplotphi)*sin(\tdplottheta))}{black!85!white}{blue}
{\draw[color=black,thick,->]  (-6,0,0) --  (6,0,0)  node[anchor=north  east]{\textbf{x}};}
{\draw[color=black,thick,->]  (0,-6,0) --  (0,6,0)  node[anchor=north  west]{\textbf{y}};}
{\draw[color=black,thick,->]  (0,0,-6) --  (0,0,6)  node[anchor=south]{\textbf{z}};}

\tdplotsphericalsurfaceplot{72}{36}{4*abs(cos(\tdplottheta))}{black!85!white}{green}
{\draw[color=black,ultra thin,->]  (-6,0,0) --  (6,0,0)  node[anchor=north  east]{};}
{\draw[color=black,ultra thin,->]  (0,-6,0) --  (0,6,0)  node[anchor=north  west]{};}
{\draw[color=black,ultra thin,->]  (0,0,-6) --  (0,0,6)  node[anchor=south]{};}

\tdplotsphericalsurfaceplot{72}{36}{4*abs(sin(\tdplotphi)*sin(\tdplottheta))}{black!85!white}{red}
{\draw[color=black,ultra thin,->]  (-6,0,0) --  (6,0,0)  node[anchor=north  east]{};}
{\draw[color=black,ultra thin,->]  (0,-6,0) --  (0,6,0)  node[anchor=north  west]{};}
{\draw[color=black,ultra thin,->]  (0,0,-6) --  (0,0,6)  node[anchor=south]{};}

\end{tikzpicture}

\end{document}

\documentclass[11pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{pstricks,pst-solides3d}

\begin{document}

\begin{pspicture}(-6,-6)(6,6)

\psset{viewpoint=100  100  100,Decran=150}
\axesIIID[showOrigin=true,mathLabel=false,axisemph=\textbf,labelsep=8pt](-7,-7,-7)(7,7,7)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=green,linecolor=black!85!white,linewidth=0.5pt,opacity=0.6,ngrid=15 24,name=green2](0,0,-2)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=blue,linecolor=black!85!white,linewidth=0.5pt,opacity=0.6,ngrid=15 24,name=blue2](-2,0,0)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=red,linecolor=black!85!white,linewidth=0.5pt,opacity=0.6,ngrid=15 24,name=red2](0,-2,0)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=green,linecolor=black!85!white,linewidth=0.5pt,opacity=0.6,ngrid=15 24,name=green1](0,0,2)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=red,linecolor=black!85!white,linewidth=0.5pt,opacity=0.6,ngrid=15 24,name=red1](0,2,0)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=blue,linecolor=black!85!white,linewidth=0.5pt,opacity=0.6,ngrid=15 24,name=blue1](2,0,0)

\end{pspicture}

\end{document}

Como posso obter o resultado pretendido e fazer com que as esferas realmente se cruzem conforme mostrado na primeira figura? Há algo que eu possa adicionar aos meus métodos acima para fazer as esferas se cruzarem? Caso contrário, existem outros métodos que posso usar para obter o resultado pretendido? A saída deve ser gráfica vetorial e usar a mesma fonte do documento principal.

Responder1

Você pode usar object=fusionpara mesclar todas as esferas em um único objeto. Para isso você também deve definir a opção solidmemory:

\documentclass[11pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{pstricks,pst-solides3d}

\begin{document}

\begin{pspicture}(-6,-6)(6,6)

\psset{viewpoint=100  100  100,Decran=150}
\axesIIID[showOrigin=true,mathLabel=false,axisemph=\textbf,labelsep=8pt](-7,-7,-7)(7,7,7)
\psset{linecolor=black!85!white,linewidth=0.5pt, opacity=0.6, strokeopacity=0.6,
       object=sphere, r=2, ngrid=15 24, action=none, solidmemory, grid}
\psSolid[fillcolor=green, name=green2](0,0,-2)
\psSolid[fillcolor=blue, name=blue2](-2,0,0)
\psSolid[fillcolor=red, name=red2](0,-2,0)
\psSolid[fillcolor=green, name=green1](0,0,2)
\psSolid[fillcolor=red, name=red1](0,2,0)
\psSolid[fillcolor=blue, name=blue1](2,0,0)

\psSolid[object=fusion, base=green1 green2 red1 red2 blue1 blue2, action=draw**]

\end{pspicture}

\end{document}

insira a descrição da imagem aqui

Responder2

\documentclass[pstricks]{standalone}
\usepackage{pst-solides3d}
\begin{document}

\begin{pspicture}(-6,-6)(6,6)
\psset{viewpoint=100 100 100,Decran=150,solidmemory,object=sphere,r=2,
   action=none,linewidth=0.5pt,ngrid=45 60,linecolor=black!85!white}
\axesIIID[mathLabel=false,axisemph=\textbf,labelsep=8pt](-7,-7,-7)(7,7,7)
\psSolid[fillcolor=green,name=green2](0,0,-2)
\psSolid[fillcolor=blue,name=blue2](-2,0,0)
\psSolid[fillcolor=red,name=red2](0,-2,0)
\psSolid[fillcolor=green,name=green1](0,0,2)
\psSolid[fillcolor=red,name=red1](0,2,0)
\psSolid[fillcolor=blue,name=blue1](2,0,0)
\psSolid[object=fusion,base=green2 blue2 red2 green1 red1 blue1,action=draw**,opacity=0.9]
\end{pspicture}

\end{document}

insira a descrição da imagem aqui

O mesmo com uma fonte de luz:

\documentclass[pstricks]{standalone}
\usepackage{pst-solides3d}
\begin{document}

\begin{pspicture}(-6,-6)(6,6)
\psset{viewpoint=60 45 30 rtp2xyz,lightsrc=viewpoint,
  Decran=60,solidmemory,object=sphere,r=2,
  action=none,linewidth=0.5pt,
  ngrid=45 60,linecolor=black!45!white}
\axesIIID[axisemph=\mathbf,labelsep=8pt](-5,-5,-5)(5,5,5)
\psSolid[fillcolor=green,name=green2](0,0,-2)
\psSolid[fillcolor=blue,name=blue2](-2,0,0)
\psSolid[fillcolor=red,name=red2](0,-2,0)
\psSolid[fillcolor=green,name=green1](0,0,2)
\psSolid[fillcolor=red,name=red1](0,2,0)
\psSolid[fillcolor=blue,name=blue1](2,0,0)
\psSolid[object=fusion,base=green2 blue2 red2 green1 red1 blue1,action=draw**,opacity=0.7,grid]
\end{pspicture}

\end{document}

insira a descrição da imagem aqui

Responder3

Aqui está uma solução para pstricks, mas não é muito boa.

Tomás

\documentclass[11pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{pstricks,pst-solides3d}

\begin{document}

\begin{pspicture}(-6,-6)(6,6)

\psset{viewpoint=100 100 100,Decran=150,solidmemory}
\axesIIID[showOrigin=true,mathLabel=false,axisemph=\textbf,labelsep=8pt](-7,-7,-7)(7,7,7)

\psSolid[object=sphere,r=2,action=draw*,fillcolor=green,linecolor=black!85!white,linewidth=0.5pt,ngrid=45 60,name=green2,action=none](0,0,-2)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=blue,linecolor=black!85!white,linewidth=0.5pt,ngrid=45 60,name=blue2,action=none](-2,0,0)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=red,linecolor=black!85!white,linewidth=0.5pt,ngrid=45 60,name=red2,action=none](0,-2,0)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=green,linecolor=black!85!white,linewidth=0.5pt,ngrid=45 60,name=green1,action=none](0,0,2)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=red,linecolor=black!85!white,linewidth=0.5pt,ngrid=45 60,name=red1,action=none](0,2,0)
\psSolid[object=sphere,r=2,action=draw*,fillcolor=blue,linecolor=black!85!white,linewidth=0.5pt,ngrid=45 60,name=blue1,action=none](2,0,0)

\psSolid[object=fusion,base=green2 blue2 red2 green1 red1 blue1,action=draw**,opacity=0.7,linewidth=0.01pt,grid]
\end{pspicture}

\end{document}

insira a descrição da imagem aqui

Responder4

Depois de experimentar as soluções fornecidas aqui, decidi dar minha própria resposta resumida. Com base nas respostas anteriores, parece que o pst-solides3dpacote é a melhor opção. (Charles Staats sugereassíntotacomo outro método possível.) Conforme apontado por Christoph, pode-se fazer com que as esferas se cruzem object=fusion(o que também requer a solidmemoryopção). Para mim, isso só funciona quando a ação do objeto de fusão está definida como draw**(veja a discussão abaixo da resposta de Christoph).

A resposta de Herbert mostra dois outros exemplos, um com linhas de grade e outro com iluminação. A resposta de Thomas S mostra um exemplo semelhante sem iluminação e sem linhas de grade.

Os exemplos de Herbert e Christoph mostram como o código pode ser escrito de forma mais eficiente.

Em todos estes exemplos, entretanto, os eixos são desenhados abaixo das esferas, pois os eixos não fazem parte da fusão. Minha solução para isso é desenhar dois conjuntos de eixos um em cima do outro. O primeiro é desenhado abaixo das esferas e o segundo é desenhado no topo das esferas, quando apropriado.

No meu exemplo, aumentei a resolução das esferas ao máximo (resoluções mais altas parecem causar falhas no compilador), para tornar as interseções o mais suaves possível. Também adicionei iluminação e reduzi a intensidade das cores para deixar o resultado mais agradável aos olhos.

Obrigado a todos pela ajuda.

EDITAR: Idioma.

\documentclass[11pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{pstricks,pst-solides3d}

\begin{document}

\begin{pspicture}(-6,-6)(6,6)

\psset{lightsrc=100 50 130,viewpoint=100 100 100,Decran=150}
\axesIIID[showOrigin=true,axisnames={}](-6.5,-6.5,-6.5)(6.5,6.5,6.5)

\psset{linewidth=0.5pt,opacity=0.7,object=sphere,r=2,ngrid=39 90,action=none,solidmemory,grid}

\psSolid[fillcolor=green!70!gray,name=green2](0,0,-2)
\psSolid[fillcolor=blue!70!gray,name=blue2](-2,0,0)
\psSolid[fillcolor=red!70!gray,name=red2](0,-2,0)
\psSolid[fillcolor=green!70!gray,name=green1](0,0,2)
\psSolid[fillcolor=red!70!gray,name=red1](0,2,0)
\psSolid[fillcolor=blue!70!gray,name=blue1](2,0,0)

\psSolid[object=fusion,base=green1 green2 red1 red2 blue1 blue2,action=draw**]

\psset{linewidth=0.8pt,opacity=1}
\axesIIID[showOrigin=false,mathLabel=false,axisemph=\textbf,labelsep=8pt](4,4,4)(6.5,6.5,6.5)

\end{pspicture}

\end{document}

Resultado final

informação relacionada