
Я пытаюсь нарисовать шесть полупрозрачных пересекающихся сфер разных цветов — по две на каждой оси x, y, z, и все они соединяются в начале координат, — как показано на рисунке ниже. Обратите внимание, как пересекаются все сферы.
Поскольку эта фигура создана в Matlab
, я попытался преобразовать фигуру в pgfplots
код, используя matlab2tikz
, но это не сработало. Ниже приведен Matlab
код для фигуры.
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
Далее я попробовал нарисовать фигуру в tikz-3dplot
и pst-solides3d
. При обоих этих методах у меня возникла проблема, что поверхности не пересекались. Вместо этого 2-мерные проекции сфер рисовались отдельно на холсте, одна поверх другой, как показано на рисунках ниже. Первая фигура — это вывод из tikz-3dplot
, а вторая фигура — это вывод из pst-solides3d
.
При использовании tikz-3dplot
у меня также возникла проблема с некоторыми осями, которые казались находящимися поверх сфер, хотя они должны были находиться внутри них (см. отрицательную половину оси Y).
Ниже приведены коды для вышеуказанных рисунков в том же порядке.
\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}
Как мне получить желаемый результат и сделать так, чтобы сферы действительно пересекались, как показано на первом рисунке? Могу ли я что-то добавить к моим методам выше, чтобы сферы пересекались? Если нет, есть ли другие методы, которые я могу использовать, чтобы получить желаемый результат? Выходные данные должны быть векторной графикой и использовать тот же шрифт, что и основной документ.
решение1
Вы можете использовать object=fusion
для объединения всех сфер в один объект. Для этого также необходимо установить опцию 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}
решение2
\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}
То же самое с источником света:
\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}
решение3
Вот решение для pstricks, но оно не очень хорошее.
Томас
\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}
решение4
Поработав с решениями, представленными здесь, я решил дать свой собственный, обобщенный ответ. Основываясь на предыдущих ответах, кажется,pst-solides3d
— лучший вариант. (Чарльз Стаатс предлагаетасимптотакак еще один возможный метод.) Как указал Кристоф, можно сделать так, чтобы сферы пересекались object=fusion
(что также требует опции solidmemory
). Для меня это работает только тогда, когда действие объекта слияния установлено на draw**
(см. обсуждение ниже ответа Кристофа).
Ответ Герберта показывает два других примера, один с линиями сетки и один с освещением. Ответ Томаса С показывает похожий пример как без освещения, так и без линий сетки.
Примеры Герберта и Кристофа показывают, как можно писать код более эффективно.
Однако во всех этих примерах оси рисуются под сферами, поскольку оси не являются частью слияния. Мое решение этой проблемы — нарисовать два набора осей друг над другом. Первый рисуется под сферами, а второй — поверх сфер, где это уместно.
В моем примере я увеличил разрешение сфер до максимума (более высокие разрешения, похоже, приводят к сбоям в работе компилятора), чтобы сделать пересечения максимально плавными. Я также добавил освещение и уменьшил интенсивность цветов, чтобы сделать результат более приятным для глаз.
Спасибо за вашу помощь.
ИЗМЕНИТЬ: Язык.
\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}