Este posibil să se redea Graphics3D
într-un proiecție izometrică ? Știu că opțiunea ViewPoint
poate fi utilizată pentru proiecția ortogonală prin specificarea, de ex. ViewPoint -> {0, Infinity, 0}
. Totuși, acest lucru nu ia mai multe infinități, așa că nu pot ViewPoint -> {Infinity, -Infinity, Infinity}
, de exemplu.
Îmi dau seama că aș putea realiza acest lucru rotind întreaga scenă aproximativ două axe și folosind o proiecție ortogonală:
Graphics3D[ Rotate[ Rotate[ Cuboid[{-.5, -.5, -.5}], Pi/4, {0, 0, 1} ], ArcTan[1/Sqrt[2]], {0, 1, 0} ], ViewPoint -> {-Infinity, 0, 0} ]
Cu toate acestea, acest lucru este destul de greoi și este „mai greu să-ți dai seama de rotațiile corecte pentru punctul de vedere I” Mă interesează. Aș prefera doar să specific octantul din care să vizualizez scena în mod izometric. Există de fapt un mod „adecvat” de a realiza acest lucru?
Comentarii
>
Răspuns
Începând cu V11.2 putem folosi o combinație de ViewProjection
și ViewPoint
:
Graphics3D[Cuboid[], ViewProjection -> "Orthographic", ViewPoint -> {1, 1, 1}]
Diverse avantaje:
v = Tuples[{Tuples[{-1, 1}, 3], IdentityMatrix[3]}]; Graphics3D[Cuboid[{-.5, -.5, -.5}, {1., 2., 4}], ViewProjection -> "Orthographic", ViewPoint -> #1, ViewVertical -> #2] & @@@ v
Răspuns
[Edit notice: Actualizat pentru a permite setarea direcției verticale a graficului și pentru a remedia o eroare .]
Iată o ușoară generalizare a răspunsului meu la Grafic 3d isometric . Pentru a obține o vizualizare izometrică, trebuie să construim un ViewMatrix
care va roti un vector de forma {±1, ±1, ±1}
la {0, 0, 1}
și proiectați ortogonal pe primele două coordonate.
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}]
Toate combinațiile de puncte de vedere și axe verticale:
Note:
Obținerea unui interval de parcela precis care include umplutura este importantă pentru calcul matricea de vizualizare corectă. Există alternative la funcția internă nedocumentată Charting`get3DPlotRange
. Alexey Popkov are o metodă aici: Cum se obține PlotRange real folosind AbsoluteOptions? Am folosit PlotRange /. AbsolutOptions[g, PlotRange]
și înmulțit cu 1.02
(nu-mi amintesc de ce nu ceva de genul 1.04
) pentru a aproxima umplutura în răspunsul meu la Plot 3D isometric .
Resursa mea de înțelegere pentru înțelegerea ViewMatrix
a fost răspunsul lui Heike în special la Extrageți valorile pentru ViewMatrix dintr-un Graphics3D .
Această actualizare răspunde la Yves „ comentariu. Lucrul cu axele m-a făcut să realizez că sistemul de coordonate este răsturnat (de la „dreptaci” la „stângaci). Prin urmare, am schimbat proiecția de la IdentityMatrix[4]
la una care răstoarnă coordonatele x & y.
Ar putea fi o idee bună să Deploy
grafica pentru a preveni rotația cu mouse-ul. Când elementele grafice sunt rotite, partea frontală resetează ViewMatrix
într-un mod destul de urât.
Comentarii
- Foarte frumos – este posibil să aliniați axa z pe verticală?
- @YvesKlett A fost ceva mai greu decât credeam că va fi, în principal pentru că am înțeles greșit ceva.
- Minunat! Acest va vă va fi util!
Răspundeți
Puteți utiliza următoarea postare -funcție proces pentru a aplica o proiecție paralelă generală:
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]}]];
Aici axes
definește proiecția lui x, y, axele z în plan 2d și pad
face o cameră pentru afișarea etichetelor axelor.
Proiecție isometrică:
g = Graphics3D[Cuboid[], Axes -> True, AxesLabel -> {X, Y, Z}]; parallelProjection[g, {{-Sqrt[3]/2, -1/2}, {Sqrt[3]/2, -1/2}, {0, 1}}]
Proiecția dulapului:
α = π/4; parallelProjection[g, {{1, 0}, {0, 1}, -{Cos[α]/2, Sin[α]/2}}]
Răspuns
Doar în cazul în care nu căutați o soluție complet corectă, ci doar o soluție ieftină.
Căutam un tip de soluție ViewPoint->{Infinity,Infinity, Infinity}
. Înlocuind Infinity cu un număr suficient de mare (în cazul meu 500) am putut obține rezultatele pe care le căutam.