É possível renderizar Graphics3D
em um projeção isométrica ? Eu sei que a opção ViewPoint
pode ser usada para projeção ortogonal especificando, por exemplo, ViewPoint -> {0, Infinity, 0}
. No entanto, isso não leva vários infinitos, então não posso fazer ViewPoint -> {Infinity, -Infinity, Infinity}
, por exemplo.
Percebo que poderia conseguir isso girando a cena inteira cerca de dois eixos e usando uma projeção ortogonal:
Graphics3D[ Rotate[ Rotate[ Cuboid[{-.5, -.5, -.5}], Pi/4, {0, 0, 1} ], ArcTan[1/Sqrt[2]], {0, 1, 0} ], ViewPoint -> {-Infinity, 0, 0} ]
No entanto, isso é bastante complicado e “é mais difícil descobrir as rotações corretas para o ponto de vista I” estou interessado. Prefiro apenas especificar o octante a partir do qual visualizar a cena isometricamente. Existe realmente uma maneira “adequada” de fazer isso?
Comentários
- Fiz uma projeção isométrica aqui: mathematica.stackexchange.com/questions/28000/isometric-3d-plot/… .
- @ MichaelE2 Ah, tudo bem, eu apenas li o corpo da pergunta e não ' não vi o que isso tinha a ver com plotagem isométrica (deveria li os comentários também). Mas acho que sua abordagem é semelhante à minha, exceto que usar dois vetores para a rotação é óbvio muito mais simples do que usar dois ângulos.
Resposta
A partir da V11.2, podemos usar uma combinação de ViewProjection
e ViewPoint
:
Graphics3D[Cuboid[], ViewProjection -> "Orthographic", ViewPoint -> {1, 1, 1}]
Várias vantagens:
v = Tuples[{Tuples[{-1, 1}, 3], IdentityMatrix[3]}]; Graphics3D[Cuboid[{-.5, -.5, -.5}, {1., 2., 4}], ViewProjection -> "Orthographic", ViewPoint -> #1, ViewVertical -> #2] & @@@ v
Resposta
[Editar aviso: Atualizado para permitir a configuração da direção vertical do gráfico e para corrigir um erro .]
Aqui está uma ligeira generalização da minha resposta para Gráfico 3D isométrico . Para obter uma visão isométrica, precisamos construir um ViewMatrix
que irá girar um vetor da forma {±1, ±1, ±1}
para {0, 0, 1}
e projete ortogonalmente nas duas primeiras coordenadas.
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}]
Todas as combinações de pontos de vista e eixos verticais:
Notes:
Obter um intervalo preciso do gráfico que inclua o preenchimento é importante para a computação a matriz de visualização correta. Existem alternativas para a função interna não documentada Charting`get3DPlotRange
. Alexey Popkov tem um método aqui: Como obter o PlotRange real usando AbsoluteOptions? Usei PlotRange /. AbsolutOptions[g, PlotRange]
e multipliquei por 1.02
(Não me lembro por que não algo como 1.04
) para aproximar o preenchimento em minha resposta a Gráfico em 3D isométrico .
Meu recurso básico para entender ViewMatrix
foi especialmente a resposta de Heike para Extraia valores para ViewMatrix de um Graphics3D .
Esta atualização é uma resposta a Yves “ comentário. Trabalhar com os eixos me fez perceber que o sistema de coordenadas é invertido (de “destro” para “canhoto). Portanto, mudei a projeção de IdentityMatrix[4]
para uma que inverte as coordenadas x & y.
Pode ser um boa ideia Deploy
os gráficos para evitar a rotação do mouse. Quando os gráficos são girados, o front end redefine o ViewMatrix
de uma forma bastante feia.
Comentários
- Muito bom – é possível alinhar o eixo z verticalmente?
- @YvesKlett Isso foi um pouco mais difícil do que eu pensei que seria, principalmente porque eu havia entendido algo errado.
- Incrível! Isso será útil!
Resposta
Você pode usar a seguinte postagem função de processo para aplicar uma projeção paralela geral:
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]}]];
Aqui axes
define a projeção de x, y, eixos z para o plano 2d e pad
abre espaço para exibir os rótulos dos eixos.
Projeção isométrica:
g = Graphics3D[Cuboid[], Axes -> True, AxesLabel -> {X, Y, Z}]; parallelProjection[g, {{-Sqrt[3]/2, -1/2}, {Sqrt[3]/2, -1/2}, {0, 1}}]
Projeção do gabinete:
α = π/4; parallelProjection[g, {{1, 0}, {0, 1}, -{Cos[α]/2, Sin[α]/2}}]
Resposta
Apenas no caso de você não estar procurando uma solução completamente correta, mas sim apenas uma solução alternativa barata.
Eu estava procurando um ViewPoint->{Infinity,Infinity, Infinity}
tipo de solução. Substituindo o Infinity por um número grande o suficiente (no meu caso, 500), poderia obter os resultados que estava procurando.