Beim Zeichnen von Ebenensätzen wie in der folgenden Abbildung
Man sieht häufig Lösungen, bei denen jedes visuelle Teil jeder Ebene in der Reihenfolge von hinten nach vorne gezeichnet wird, wie der hier enthaltene Code. Ein weiteres Beispiel finden Sie hier (sich kreuzende Ebenen).
Frage: Ist es möglich, in TikZ die Ebenen mithilfe von 3D-Koordinaten zu zeichnen und einen Blickwinkel auszuwählen, ohne die Ansicht vorher berechnen zu müssen?
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}
\usetikzlibrary{intersections}
\begin{document}
\pagecolor{blue!30}
\pagestyle{empty}
\begin{tikzpicture}[scale=1.6]
\definecolor{bg}{RGB}{246,202,203}
\coordinate (A) at (0.95,3.41);
\coordinate (B) at (1.95,0.23);
\coordinate (C) at (3.95,1.23);
\coordinate (D) at (2.95,4.41);
\coordinate (E) at (1.90,3.30);
\coordinate (F) at (0.25,0.45);
\coordinate (G) at (2.25,1.45);
\coordinate (H) at (3.90,4.30);
\coordinate (I) at (-0.2,1.80);
\coordinate (J) at (2.78,1.00);
\coordinate (K) at (4.78,2.00);
\coordinate (L) at (1.80,2.80);
\path[name path=AB] (A) -- (B);
\path[name path=CD] (C) -- (D);
\path[name path=EF] (E) -- (F);
\path[name path=IJ] (I) -- (J);
\path[name path=KL] (K) -- (L);
\path[name path=HG] (H) -- (G);
\path[name path=IL] (I) -- (L);
\path [name intersections={of=AB and EF,by=M}];
\path [name intersections={of=EF and IJ,by=N}];
\path [name intersections={of=AB and IJ,by=O}];
\path [name intersections={of=AB and IL,by=P}];
\path [name intersections={of=CD and KL,by=Q}];
\path [name intersections={of=CD and HG,by=R}];
\path [name intersections={of=KL and HG,by=S}];
\path[name path=NS] (N) -- (S);
\path[name path=FG] (F) -- (G);
\path [name intersections={of=NS and AB,by=T}];
\path [name intersections={of=FG and AB,by=U}];
\draw[thick, color=white, fill=bg] (A) -- (B) -- (C) -- (D) -- cycle;
%\draw[thick, color=white, fill=bg] (E) -- (F) -- (G) -- (H) -- cycle;
%\draw[thick, color=white, fill=bg] (I) -- (J) -- (K) -- (L) -- cycle;
\draw[thick, color=white, fill=gray!80] (P) -- (O) -- (I) -- cycle;
\draw[thick, color=white, fill=gray!80] (O) -- (J) -- (K) -- (Q) -- cycle;
\draw[thick, color=white, fill=gray!40] (H) -- (E) -- (M) -- (R) -- cycle;
\draw[thick, color=white, fill=gray!40] (M) -- (N) -- (T) -- cycle;
\draw[thick, color=white, fill=gray!40] (N) -- (F) -- (U) -- (O) -- cycle;
\end{tikzpicture}
\end{document}
Antwort1
Dies ist eher eine lustige Antwort mit der Nachricht, dass es machbar ist, aber etwas Geduld erfordert. Außerdem erlaube ich den Breitengradwinkel Theta nur im Bereich über 90 Grad. In diesem Fall gibt es nur zwei Fälle, die unterschieden werden müssen, d. h. dies ist nicht der allgemeine Fall. Es gibt vier Fälle, die durch zwei Binärzahlen unterschieden werden
- das Vorzeichen der Projektion der 3D-x-Achse auf die x-Richtung des Bildschirms,
\xproj
. - das Vorzeichen von cos(theta),
\zproj
(in den Konventionen von tikz-3dplot liegt theta zwischen 0 und 180, und der Äquator liegt bei theta=90). Dieses Vorzeichen gibt an, ob man sich auf der Süd- oder Nordhalbkugel befindet.
Das heißt, wir werden die Fälle unterscheiden \xproj
und \zproj
ob sie positiv oder negativ sind. Abhängig von diesen Vorzeichen ändert sich die Reihenfolge, in der die Ebenen gezeichnet werden. Um ein wenig Übersichtlichkeit zu wahren, enthält diese Antwort ein Makro \DrawSinglePlane{<plane number>
, sodass eine Änderung der Zeichenreihenfolge lediglich einer Permutation der Liste von plane number
s entspricht.
\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usetikzlibrary{calc}
\newcommand{\DrawPlane}[3][]{\draw[#1]
(-1*\PlaneScale,{\PlaneScale*cos(#2)},{\PlaneScale*sin(#2)})
-- ++ (2*\PlaneScale,0,0)
-- ++ (0,{sqrt(3)*\PlaneScale*cos(#3)},{sqrt(3)*\PlaneScale*sin(#3)})
-- ++ (-2*\PlaneScale,0,0) -- cycle;}
\newcommand{\DrawSinglePlane}[2][]{\ifcase#2
\or
\DrawPlane[fill=blue,#1]{210}{240} %left bottom
\or
\DrawPlane[fill=red,#1]{-30}{-60} % right bottom
\or
\DrawPlane[fill=purple,#1]{210}{180} % bottom left
\or
\DrawPlane[fill=purple,#1]{210}{0} % bottom middle
\or
\DrawPlane[fill=purple,#1]{-30}{0} % bottom right
\or
\DrawPlane[fill=blue,#1]{90}{240} % left top
\or
\DrawPlane[fill=red,#1]{90}{-60} % right middle
\or
\DrawPlane[fill=red,#1]{90}{120} % right top
\or
\DrawPlane[fill=blue,#1]{90}{60} % left top
\fi
}
\begin{document}
\foreach \X in {0,5,...,355}
{\tdplotsetmaincoords{90+40*sin(\X)}{\X} % the first argument cannot be larger than 90
\pgfmathsetmacro{\PlaneScale}{1}
\begin{tikzpicture}
\path[use as bounding box] (-4*\PlaneScale,-4*\PlaneScale) rectangle (4*\PlaneScale,4*\PlaneScale);
\begin{scope}[tdplot_main_coords]
% \draw[thick,->] (0,0,0) -- (2,0,0) node[anchor=north east]{$x$};
% \draw[thick,->] (0,0,0) -- (0,2,0) node[anchor=north west]{$y$};
% \draw[thick,->] (0,0,0) -- (0,0,1.5) node[anchor=south]{$z$};
\path let \p1=(1,0,0) in
\pgfextra{\pgfmathtruncatemacro{\xproj}{sign(\x1)}\xdef\xproj{\xproj}};
\pgfmathtruncatemacro{\zproj}{sign(cos(\tdplotmaintheta))}
\xdef\zproj{\zproj}
% \node[anchor=north west] at (current bounding box.north west)
% {\tdplotmaintheta,\tdplotmainphi,\xproj,\zproj};
\ifnum\zproj=1
\ifnum\xproj=1
\foreach \X in {2,1,5,4,3,7,6,9,8}
{\DrawSinglePlane{\X}}
\else
\foreach \X in {1,...,9}
{\DrawSinglePlane{\X}}
\fi
\else
\ifnum\xproj=1
\foreach \X in {9,8,7,6,3,4,5,2,1}
{\DrawSinglePlane{\X}}
\else
\foreach \X in {8,9,6,7,3,5,4,1,2}
{\DrawSinglePlane{\X}}
\fi
\fi
\end{scope}
\end{tikzpicture}}
\end{document}
Und für\tdplotsetmaincoords{90+40*cos(\X)}{\X}
Ein möglicherweise wichtiger Kommentar betrifft pgfplots. Im Prinzip kann man Patchplots verwenden, um dasselbe zu tun. pfplots verfügt, wie in den Kommentaren erläutert, über einige Möglichkeiten, die Sortierung vorzunehmen.
AKTUALISIEREN: Deckt jetzt das gesamte Sortiment ab.
WICHTIGER HINWEIS: Bei diesen Animationen kam weder Ente noch Murmeltier zu Schaden. ;-)
Antwort2
Ist Tikz eine zwingende Voraussetzung? Ich habe festgestellt, dass Asymptote (in TeXLive enthalten) ein hervorragendes Werkzeug für solche Aufgaben ist. Unten finden Sie ein leicht bearbeitetes Beispiel aus demAsymptote-Galerie.
Sie können den Blickwinkel einfach durch Ändern der Zeile ändern, die mit beginnt currentprojection
.
size(6cm,0);
import bsp;
real u=2.5;
real v=1;
currentprojection = oblique;
path3 y=plane((2u,0,0),(0,2v,0),(-u,-v,0));
path3 a=rotate(45,X)*y;
path3 l=rotate(-45,Z)*rotate(45,Y)*rotate(45,Z)*y;
path3 g=rotate(45,X)*rotate(45,Y)*rotate(45,Z)*y;
face[] faces;
filldraw(faces.push(a),project(a),gray);
filldraw(faces.push(l),project(l),blue);
filldraw(faces.push(g),project(g),pink);
add(faces);
Es ergibt sich folgende Abbildung:
Während die Änderung einer Zeile zu currentprojection = perspective(5,2,3);
folgender Zahl führt:
Ein exzellentesAsymptote-Tutorial wurde von Charles Staats geschrieben, einem Doktoranden der Universität von Chicago.