35

Some idea of how to do something similar to the image, but with any 3d object

Any body in 3d

user64494
  • 26,149
  • 4
  • 27
  • 56
zeros
  • 2,263
  • 1
  • 14
  • 18
  • Possible duplicate: https://mathematica.stackexchange.com/questions/164663/2d-projection-of-a-3d-surface. This also seems relevant to the image above, depending on what the dashed lines represent: https://mathematica.stackexchange.com/questions/45410/sketch-type-graphics-with-transparency-and-dashed-hidden-lines – Michael E2 Jun 04 '19 at 00:37

2 Answers2

34

Update 2: The function projectToWalls does not work in version 12.0 because the function PlotRange no longer works. To fix the issue, replace PlotRange with plotRange where

 plotRange = PlotRange/.AbsoluteOptions[#, PlotRange] &;

in the definition of projectToWalls.

Original answer:

You can post-process a Graphics3D object to project the lines to the left, back and bottom planes using a function like:

ClearAll[projectToWalls]
projectToWalls =  Module[{pr = PlotRange[#]}, 
    Normal[#] /. Line[x_, ___] :> 
       {Line[x], Line /@ (x /. 
         {{{a_, b_, c_} :> {pr[[1, 1]], b, c}}, 
          {{a_, b_, c_} :> {a, pr[[2, 2]], c}}, 
          {{a_, b_, c_} :> {a, b, pr[[3, 1]]}}})}] &;

Examples:

pp1 = ParametricPlot3D[{{4 + (3 + Cos[v]) Sin[u], 
        4 + (3 + Cos[v]) Cos[u], 4 + Sin[v]}, {8 + (3 + Cos[v]) Cos[u], 
        3 + Sin[v], 4 + (3 + Cos[v]) Sin[u]}}, {u, 0, 2 Pi}, {v, 0, 2 Pi},
    PlotStyle -> {Red, Green}];

projectToWalls @ pp1

enter image description here

projectToWalls @
 Graphics3D[{White, MeshPrimitives[Tetrahedron[], 1], 
   MeshPrimitives[Cuboid[{0, 1/2, 0}], 1]}, 
  PlotRange -> {{-1, 2}, {-1, 2}, {-1, 2}}, Background -> Black]

enter image description here

Update: Taking Roman's idea a step further using Textured polygons:

SeedRandom[1234];
P = Graphics3D[{Hue@RandomReal[], #} & /@ Cuboid @@@ RandomReal[{0, 1}, {10, 2, 3}]];
pr = PlotRange[P];
rect = {#, {#2[[1]], #[[-1]]}, #2, {#[[1]], #2[[-1]]}} & @@ Transpose[pr[[{##}]]] &;
texturedPoly = {Texture[Rasterize[#, Background -> None]], 
    Polygon[#2, VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]} &;
{left, back, bottom} = Show[P, ViewPoint -> #, Boxed -> False, Axes -> False, 
    Lighting -> "Neutral"] & /@ {Right, Front, Top}; 
leftWall = Prepend[#, pr[[1, 1]] - 1] & /@ rect[2, 3];
backWall = Insert[#, pr[[2, 1]] + 2, 2] & /@ rect[1, 3];
bottomWall = Append[#, pr[[3, 1]] - 1] & /@ rect[1, 2];

Graphics3D[{Opacity[.2], P[[1]], EdgeForm[None], Opacity[1], MapThread[texturedPoly, {{left, back, bottom}, {leftWall, backWall, bottomWall}}]}, BoxRatios -> 1, PlotRange -> {{-1, 1.5}, {-.5, 2.1}, {-1, 1.5}}]

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896
  • projectToWalls no longer seems to work on Version 12. Suggestions? Thanks. – bbgodfrey Dec 06 '19 at 13:21
  • 1
    @bbgodfrey, thank you for bringing this issue to my attention. I updated the post with a fix that works in v12.0 (Wolfram Cloud). – kglr Dec 06 '19 at 13:42
  • It certainly does. Many thanks. – bbgodfrey Dec 06 '19 at 14:49
  • How can I change the color of each projected images with projectToWalls? – emnha Oct 12 '23 at 23:35
  • try Line[x_, ___] :> {Line[x], MapThread[{#, Line@#2} &]@{{Cyan, Orange, Magenta}, (x /. {{{a_, b_, c_} :> {pr[[1, 1]], b, c}}, {{a_, b_, c_} :> {a, pr[[2, 2]], c}}, {{a_, b_, c_} :> {a, b, pr[[3, 1]]}}})}} – kglr Oct 13 '23 at 10:25
15

If you only need the 2D projection images, you can just project the 3D image from the six cardinal directions:

SeedRandom[1234];
P = Graphics3D[{RandomColor[], #} & /@ Cuboid @@@ RandomReal[{0, 1}, {10, 2, 3}]]

enter image description here

Show[P, ViewPoint -> #] & /@ {{∞,0,0}, {-∞,0,0}, {0,∞,0}, {0,-∞,0}, {0,0,∞}, {0,0,-∞}}

enter image description here

Working with the ViewVertical option might also help.

Roman
  • 47,322
  • 2
  • 55
  • 121