Dibujar trazados de superficies 3D que se cruzan

Dibujar trazados de superficies 3D que se cruzan

Estoy intentando dibujar seis esferas semitransparentes que se cruzan y de diferentes colores (dos en cada eje x, y, z y todas uniéndose en el origen) como se muestra en la siguiente figura. Observe cómo se cruzan todas las esferas.

(Aproximadamente) resultado previsto

Dado que esta figura se creó en Matlab, intenté convertir la figura a pgfplotscódigo usando matlab2tikz, pero esto no funcionó. A continuación se muestra el Matlabcódigo de la 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

Luego intenté dibujar la figura en tikz-3dploty pst-solides3d. Con ambos métodos, tuve el problema de que las superficies no se cruzaban. En cambio, se dibujaron proyecciones bidimensionales de las esferas por separado en el lienzo, una encima de la otra, como se muestra en las figuras siguientes. La primera figura es la salida de tikz-3dploty la segunda figura es la salida de pst-solides3d.

Intento con tikz-3dplot Intento con pst-solides3d

Con tikz-3dplot, también tuve un problema con ciertos ejes que parecían estar encima de las esferas, cuando más bien deberían parecer estar dentro de ellas (ref. la mitad negativa del eje y).

A continuación se muestran los códigos de las figuras anteriores, en el mismo orden.

\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}

¿Cómo puedo obtener el resultado deseado y hacer que las esferas realmente se crucen como se muestra en la primera figura? ¿Hay algo que pueda agregar a mis métodos anteriores para hacer que las esferas se crucen? Si no es así, ¿existen otros métodos que pueda utilizar para obtener el resultado deseado? El resultado debe ser gráficos vectoriales y utilizar la misma fuente que el documento principal.

Respuesta1

Puedes utilizar object=fusionpara fusionar todas las esferas en un solo objeto. Para eso también debes configurar la opción 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}

ingrese la descripción de la imagen aquí

Respuesta2

\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}

ingrese la descripción de la imagen aquí

Lo mismo con una fuente 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}

ingrese la descripción de la imagen aquí

Respuesta3

Aquí hay una solución para pstricks, pero no es muy buena.

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}

ingrese la descripción de la imagen aquí

Respuesta4

Después de probar las soluciones proporcionadas aquí, decidí dar mi propia respuesta resumida. Según las respuestas anteriores, parece que el pst-solides3dpaquete es la mejor opción. (Charles Staats sugiereasíntotacomo otro método posible.) Como señaló Christoph, se puede hacer que las esferas se crucen object=fusion(lo que también requiere la solidmemoryopción). Para mí, esto sólo funciona cuando la acción del objeto de fusión está configurada en draw**(consulte la discusión a continuación sobre la respuesta de Christoph).

La respuesta de Herbert muestra otros dos ejemplos, uno con líneas de cuadrícula y otro con iluminación. La respuesta de Thomas S muestra un ejemplo similar sin iluminación y sin rejillas.

Tanto el ejemplo de Herbert como el de Christoph muestran cómo se puede escribir código de manera más eficiente.

Sin embargo, en todos estos ejemplos, los ejes se dibujan debajo de las esferas, ya que los ejes no forman parte de la fusión. Mi solución a esto es dibujar dos conjuntos de ejes uno encima del otro. El primero se dibuja debajo de las esferas y el segundo se dibuja encima de las esferas cuando corresponda.

En mi ejemplo, he aumentado la resolución de las esferas al máximo (las resoluciones más altas parecen hacer que el compilador falle), para que las intersecciones sean lo más suaves posible. También agregué iluminación y reduje la intensidad de los colores para que el resultado fuera más agradable a la vista.

Gracias por toda tu ayuda.

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

información relacionada