Czy możliwe jest renderowanie Graphics3D
w rzut izometryczny ? Wiem, że opcja ViewPoint
może być użyta do rzutowania ortogonalnego, podając np. ViewPoint -> {0, Infinity, 0}
. Nie wymaga to jednak wielu nieskończoności, więc nie mogę na przykład wykonać ViewPoint -> {Infinity, -Infinity, Infinity}
.
Zdaję sobie sprawę, że mogę to osiągnąć, obracając całą scenę około dwóch osi i używając rzutu ortogonalnego:
Graphics3D[ Rotate[ Rotate[ Cuboid[{-.5, -.5, -.5}], Pi/4, {0, 0, 1} ], ArcTan[1/Sqrt[2]], {0, 1, 0} ], ViewPoint -> {-Infinity, 0, 0} ]
Jest to jednak dość kłopotliwe i trudniej jest ustalić prawidłowe obroty punktu widzenia I ” Jestem zainteresowany. Wolę tylko określić oktant, z którego ma być oglądana scena izometrycznie. Czy rzeczywiście istnieje „właściwy” sposób, aby to osiągnąć?
Komentarze
- Wykonałem tutaj rzut izometryczny: mathematica.stackexchange.com/questions/28000/isometric-3d-plot/… .
- @ MichaelE2 No dobra, przeczytałem tylko treść pytania i nie ' nie widziałem, co to ma wspólnego z kreśleniem izometrycznym (powinno przeczytałem również komentarze). Ale wydaje mi się, że twoje podejście jest podobne do mojego, z tą różnicą, że użycie dwóch wektorów do rotacji to obv i to znacznie prostsze niż używanie dwóch kątów.
Odpowiedź
Od wersji 11.2 możemy używać kombinacji ViewProjection
i ViewPoint
:
Graphics3D[Cuboid[], ViewProjection -> "Orthographic", ViewPoint -> {1, 1, 1}]
Różne perspektywy:
v = Tuples[{Tuples[{-1, 1}, 3], IdentityMatrix[3]}]; Graphics3D[Cuboid[{-.5, -.5, -.5}, {1., 2., 4}], ViewProjection -> "Orthographic", ViewPoint -> #1, ViewVertical -> #2] & @@@ v
Odpowiedź
[Edytuj powiadomienie: Zaktualizowano, aby umożliwić ustawienie pionowego kierunku wykresu i naprawić błąd .]
Oto niewielkie uogólnienie mojej odpowiedzi na temat Izometryczny wykres 3D . Aby uzyskać widok izometryczny, musimy skonstruować ViewMatrix
, który będzie obracał wektor o postaci {±1, ±1, ±1}
do {0, 0, 1}
i rzutuj prostopadle na pierwsze dwie współrzędne.
ClearAll[isometricView]; isometricView[ g_Graphics3D, (* needed only for PlotRange *) v_ /; Equal @@ Abs[N@v] && 1. + v[[1]] != 1., (* view point {±1, ±1, ±1} *) vert_: {0, 0, 1}] := (* like ViewVertical; default: z-axis *) {TransformationMatrix[ RescalingTransform[ EuclideanDistance @@ Transpose[Charting`get3DPlotRange@ g] {{-1/2, 1/2}, {-1/2, 1/2}, {-1/2, 1/2}}]. RotationTransform[{-v, {0, 0, 1}}]. RotationTransform[{vert - Projection[vert, v], {0, 0, 1} - Projection[{0, 0, 1}, v]}]. RotationTransform[Mod[ArcTan @@ Most[v], Pi], v]. TranslationTransform[-Mean /@ (Charting`get3DPlotRange@ g)]], {{0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}}; foo = Graphics3D[Cuboid[{-.5, -.5, -.5}, {1., 2., 4}]]; Show[foo, ViewMatrix -> isometricView[foo, {1, 1, 1}, {0, 0, 1}], ImagePadding -> 20, Axes -> True, AxesLabel -> {x, y, z}] Show[foo, ViewMatrix -> isometricView[foo, {-1, 1, 1}, {1, 1, 0}], ImagePadding -> 20, Axes -> True, AxesLabel -> {x, y, z}]
Wszystkie kombinacje punktów widzenia i osi pionowych:
Uwagi:
Uzyskanie dokładnego zakresu wykresu, który obejmuje dopełnienie, jest ważne dla obliczeń poprawna macierz widoku. Istnieją alternatywy dla nieudokumentowanej funkcji wewnętrznej Charting`get3DPlotRange
. Alexey Popkov ma tutaj metodę: Jak uzyskać prawdziwy PlotRange za pomocą AbsoluteOptions? Użyłem PlotRange /. AbsolutOptions[g, PlotRange]
i pomnożyłem przez 1.02
(Nie pamiętam, dlaczego nie coś takiego jak 1.04
), aby przybliżyć wypełnienie w mojej odpowiedzi na Izometryczny wykres 3D .
Moje główne źródło zrozumienia ViewMatrix
było szczególnie odpowiedzią Heike na Wyodrębnij wartości dla ViewMatrix z Graphics3D .
Ta aktualizacja jest odpowiedzią na Yves „ komentarz Praca z osiami uświadomiła mi, że układ współrzędnych jest odwrócony (z „praworęcznych” na „leworęcznych”). Dlatego zmieniłem odwzorowanie z IdentityMatrix[4]
na takie, które odwraca współrzędne x &.
To może być dobrym pomysłem jest Deploy
grafiki, aby zapobiec jej obracaniu przez mysz. Kiedy grafika jest obracana, front end resetuje ViewMatrix
w raczej brzydki sposób.
Komentarze
- Bardzo ładnie – czy można wyrównać oś Z w pionie?
- @YvesKlett To było trochę trudniejsze niż myślałem, głównie dlatego, że coś źle zrozumiałem.
- Niesamowite! To przyda się !
Odpowiedź
Możesz skorzystać z następującego posta -procesuj funkcję, aby zastosować ogólne odwzorowanie równoległe:
parallelProjection[g_Graphics3D, axes_, pad_: 0.15] := Module[{pr3, pr2, ar, t}, pr3 = {-pad, pad} (#2 - #) & @@@ # + # &@Charting`get3DPlotRange@g; pr2 = MinMax /@ Transpose[[email protected]]; ar = Divide @@ Subtract @@@ pr2; t = AffineTransform@Append[Transpose@axes, {0, 0, -1}]; t = RescalingTransform@Append[pr2, pr3[[3]]].t; Show[g, AspectRatio -> 1/ar, ViewMatrix -> {TransformationMatrix[t], IdentityMatrix[4]}]];
Tutaj axes
definiuje rzutowanie x, y, z osi do płaszczyzny 2d i pad
tworzy miejsce na wyświetlanie etykiet osi.
Rzut izometryczny:
g = Graphics3D[Cuboid[], Axes -> True, AxesLabel -> {X, Y, Z}]; parallelProjection[g, {{-Sqrt[3]/2, -1/2}, {Sqrt[3]/2, -1/2}, {0, 1}}]
Projekcja szafki:
α = π/4; parallelProjection[g, {{1, 0}, {0, 1}, -{Cos[α]/2, Sin[α]/2}}]
Odpowiedź
Na wypadek gdybyś nie szukał całkowicie poprawnego rozwiązania, a zamiast tego po prostu taniego obejścia.
Szukałem ViewPoint->{Infinity,Infinity, Infinity}
rozwiązania. Zamieniając Infinity na wystarczająco dużą liczbę (w moim przypadku 500) mogłem uzyskać wyniki, których szukałem.