Je možné vykreslit Graphics3D
v izometrická projekce ? Vím, že možnost ViewPoint
lze použít pro ortogonální projekci zadáním, např. ViewPoint -> {0, Infinity, 0}
. To však nezabere více nekonečností, takže nemohu například ViewPoint -> {Infinity, -Infinity, Infinity}
.
Uvědomuji si, že toho mohu dosáhnout otočením celé scény o dvou osách a pomocí ortogonální projekce:
Graphics3D[ Rotate[ Rotate[ Cuboid[{-.5, -.5, -.5}], Pi/4, {0, 0, 1} ], ArcTan[1/Sqrt[2]], {0, 1, 0} ], ViewPoint -> {-Infinity, 0, 0} ]
To je však poněkud těžkopádné a je těžší zjistit správné otáčky pro hledisko I “ Zajímám se. Raději jen zadám oktant, ze kterého se bude scéna zobrazovat izometricky. Existuje skutečně „správný“ způsob, jak toho dosáhnout?
Komentáře
- Zde jsem provedl izometrickou projekci: mathematica.stackexchange.com/questions/28000/isometric-3d-plot/… .
- @ MichaelE2 No dobře, přečetl jsem pouze tělo otázky a ' neviděl, co to má společného s izometrickým vykreslením (mělo by přečetli si také komentáře). Ale myslím, že váš přístup je podobný mému, kromě toho, že použití dvou vektorů pro rotaci je obv jednodušší než použití dvou úhlů.
Odpověď
Od verze 11.2 můžeme použít kombinaci ViewProjection
a ViewPoint
:
Graphics3D[Cuboid[], ViewProjection -> "Orthographic", ViewPoint -> {1, 1, 1}]
Různé výhody:
v = Tuples[{Tuples[{-1, 1}, 3], IdentityMatrix[3]}]; Graphics3D[Cuboid[{-.5, -.5, -.5}, {1., 2., 4}], ViewProjection -> "Orthographic", ViewPoint -> #1, ViewVertical -> #2] & @@@ v
Odpověď
[Upravit upozornění: Aktualizováno, aby bylo možné nastavit svislý směr grafu a opravit chybu .]
Zde je mírné zobecnění mé odpovědi na izometrické 3d vykreslení . Chcete-li získat izometrický pohled, musíme zkonstruovat ViewMatrix
, který bude otáčet vektor ve tvaru {±1, ±1, ±1}
do {0, 0, 1}
a promítat kolmo na první dvě souřadnice.
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}]
Všechny kombinace hledisek a svislých os:
Poznámky :
Získání přesného rozsahu vykreslení včetně výplně je pro výpočet důležité správná matice zobrazení. K nezdokumentované interní funkci Charting`get3DPlotRange
existují alternativy. Alexey Popkov zde má metodu: Jak získat skutečný PlotRange pomocí AbsoluteOptions? Použil jsem PlotRange /. AbsolutOptions[g, PlotRange]
a vynásobil 1.02
(Nevzpomínám si, proč ne něco jako 1.04
) k aproximaci výplně v mé odpovědi na Izometrické 3D vykreslování .
Můj zdroj, který slouží k porozumění ViewMatrix
, byl zejména Heikeovou odpovědí na Extrahovat hodnoty pro ViewMatrix z Graphics3D .
Tato aktualizace reaguje na Yves „ komentář. Práce s osami mě přiměla si uvědomit, že souřadný systém je převrácený (z „praváka“ na „leváka“). Proto jsem změnil projekci z IdentityMatrix[4]
na projekci, která převrátí x & y souřadnic.
Může to být dobrý nápad Deploy
grafiku zabránit rotaci myší. Když se grafika otáčí, frontend resetuje ViewMatrix
docela ošklivým způsobem.
Komentáře
- Velmi pěkné – je možné svisle zarovnat osu z?
- @YvesKlett To bylo trochu těžší, než jsem si myslel, hlavně proto, že jsem něco nepochopil.
- Úžasné! Toto přijde vhod!
Odpověď
Můžete použít následující příspěvek -procesová funkce pro použití obecné paralelní projekce:
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]}]];
Zde axes
definuje projekci x, y, z os do 2D roviny a pad
vytvoří prostor pro zobrazení štítků os.
Izometrická projekce:
g = Graphics3D[Cuboid[], Axes -> True, AxesLabel -> {X, Y, Z}]; parallelProjection[g, {{-Sqrt[3]/2, -1/2}, {Sqrt[3]/2, -1/2}, {0, 1}}]
Projekce kabinetu:
α = π/4; parallelProjection[g, {{1, 0}, {0, 1}, -{Cos[α]/2, Sin[α]/2}}]
Odpověď
Jen pro případ, že nehledáte úplně správné řešení, ale pouze levné řešení.
Hledal jsem ViewPoint->{Infinity,Infinity, Infinity}
druh řešení. Nahrazením Infinity dostatečně velkým číslem (v mém případě 500) jsem mohl získat výsledky, které jsem hledal.