I am working on a project that involves SciDraw. The SciDraw software is great for making high quality plots, but it is not compatible with any 3D plots.
I need to add some relatively simple 3D plots -- just a few points with lines connecting them (e.g. to draw a tetrahedron). I have started researching how to do this using a projection and found valuable resources here and here. This may not even turn out to be useful for the project at hand, but I've become curious how Mathematica plots 3D points (objects, curves, etc.) into 2D (i.e. my computer screen) while maintaining the 3D view.
My attempts to replicate this so far have been only partially successful. I have been testing my function by trying to reproduce the 3D rendering of a cube:
Graphics3D[Cube[], ViewPoint -> #] & /@ {{1, 0, 0}, {1, 1, 0}, {1, 1, 1}}
My first attempt was as follows:
dropDimension[{x_, y_, z_}, {a_, b_, c_}] :=
Block[{orthogonalVecs = {{-b, a, 0}, {-c, 0, a}, {0, -c, b}}, s, t,
u, v, equation},
{u, v} =
Select[DeleteDuplicates[orthogonalVecs],
EuclideanDistance[#, {0, 0, 0}] != 0 &][[;; 2]];
equation =
MaximalBy[{{1, u[[1]]*v[[2]] - v[[1]]*u[[2]]}, {2,
u[[1]]*v[[3]] - v[[1]]*u[[3]]}, {3,
u[[2]]*v[[3]] - v[[2]]*u[[3]]}}, #[[2]]^2 &][[1]];
Switch[equation[[1]],
1, {s = ((x - a)*v[[2]] - (y - b)*v[[1]])/equation[[2]],
t = ((y - b)*u[[1]] - (x - a)*u[[2]])/equation[[2]]},
2, {s = ((x - a)*v[[3]] - (z - c)*v[[1]])/equation[[2]],
t = ((z - c)*u[[1]] - (x - a)*u[[3]])/equation[[2]]},
3, {s = ((y - b)*v[[3]] - (x - a)*v[[2]])/equation[[2]],
t = ((z - c)*u[[2]] - (y - b)*u[[3]])/equation[[2]]}
]
]
I then generated a random sampling of points on the surface of a cube using:
cubePts =
Table[ReplacePart[Table[RandomReal[{-1, 1}], 3],
RandomChoice[Range[3]] -> RandomChoice[{-1, 1}]], 10000];
Finally, I plotted all the points:
Table[ListPlot[dropDimension[#, viewPoint] & /@ cubePts,
PlotRange -> All], {viewPoint, {{1, 0, 0}, {1, 1, 0}, {1, 1, 1}}}]
My main issue with my current solution is that you can't see the depth of the original object (the cube surface). For example, from {1,1,0}
, I would expect the center (s=1) to be taller than the surrounding areas. My naïve attempt to introduce this depth involved calculating the depth of each point as the distance perpendicular to the viewing plane (i.e. in the axis of the view point) between a given point and the view point. However, I am still uncertain of the correct depth function, though I am currently using depth = ({a, b, c} - {x, y, z}) . {a, b, c}
.
Any insight as how to Mathematica renders 3D plots into 2D, or how I might be able to mimic this behavior in a relatively simple function? Or, if there is a built-in function to do something similar, I would love to know -- my searches through the documentation haven't produced anything yet.