13
$\begingroup$

I am currently trying to combine several 2D plots into one big 3D plot. The 2D-plots are simply input-results from calculations (so these things have 2D coördinates (x,y)). The results depend on an integer parameter n, and what I now want to do is combine these results on one big plot (with n on the z-axis).

I tried to do this with graphics3D, but the problem is that i the need the command Texture[] which rasterizes the background and thus yields difficulties when combining the plots. Is there a way to get the background out?

An example of my problem is given (when you look for example at the function y^2==a*x, where you want to vary the parameter a):

Show[Table[ Graphics3D[{Texture[ ContourPlot[y^2 == a*x, {x, 0, 2}, {y, -2, 2}, Frame -> False, ContourStyle -> Hue[(a - 1)/4], Background -> None]], Polygon[{{-\[Pi]/2, -\[Pi]/2, a}, {\[Pi]/2, -\[Pi]/2, a}, {\[Pi]/2, \[Pi]/2, a}, {-\[Pi]/2, \[Pi]/2, a}}, VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}, Lighting -> "Neutral"], {a, 1, 5, 0.5}]]

which yields enter image description here

What I want to have is something like:

enter image description here

I don't know if there are any ways to get the background of Texture[] away ?

The actual question:

Given a set of 2D plots (which depend on some paramter "a"), how can I stack these 2D plots in a 3D plot (where the additional axis contains my parameter "a") without losing the background transparency of the different independent plots ?

Context of the question:

For example if you want to calculate a phase diagram of a physical system, then you will compare the free energy F(p,V,T) of the different phases for different values of T. Depending on which one is the smallest you can assign a color to the 2D plane, leading to a 2D "plot" of colors with coördinates. If I want to know how my different phases behave (in the (p,V)-plane) as a function of T, then I need to stack my different 2D planes.

$\endgroup$
7
  • $\begingroup$ related ( with images.. ) mathematica.stackexchange.com/questions/35581/… $\endgroup$
    – george2079
    Commented Mar 11, 2015 at 15:48
  • 1
    $\begingroup$ Some related questions: 159, 1413, 23665 $\endgroup$
    – Michael E2
    Commented Mar 11, 2015 at 15:53
  • $\begingroup$ do you specifically need to use Texture for some reason ? $\endgroup$
    – george2079
    Commented Mar 11, 2015 at 15:54
  • $\begingroup$ @george2079, no, not at all! I'm just new to this and Texture[] seemed like the way to go. I just want to know if there is a way to stack 2D plots into a 3D plot without losing the transparancy of my white background. $\endgroup$
    – Nick
    Commented Mar 11, 2015 at 15:59
  • $\begingroup$ A general remark: I'm not looking to stack contourplots, there are indeed easier ways to do this. I'm looking on how to stack individual (more or less independent) 2D plots. $\endgroup$
    – Nick
    Commented Mar 11, 2015 at 16:07

5 Answers 5

10
$\begingroup$

Here's one way:

ContourPlot3D[y^2 == a*x,
   {x, 0, 2}, {y, -2, 2}, {a, 0.9, 5.1}, 
   MeshFunctions -> {#3 &}, Mesh -> {Table[a, {a, 1, 5, 0.5}]}, 
   ContourStyle -> None, BoundaryStyle -> None] /. 
 GraphicsComplex[p_, g_, opts___] :> 
  GraphicsComplex[p, 
   g /. Line[v_] :> {Hue[((p ~Part~ v[[1]] ~Part~ 3) - 1)/4], Thick, Line[v]}, opts]

Mathematica graphics

Response to updated question

It's not clear that the above method cannot be adapted to the "context of the question", as described. But let's address the problem of assembling a more-or-less random list of plots that "depend on an integer parameter n."

Show[MapIndexed[# /. {Graphics[g_, opts___] :> 
      Graphics3D[g /. p : {_Real, _Real} :> Join[p, #2], 
       FilterRules[{opts}, Graphics3D]]} &,
  plots
  ],
 BoxRatios -> {1, 1, 1}, Axes -> True]

Note: it will fail if the graphics contain Text/Inset objects using the offset and direction parameters. They ought to remain 2D coordinates. Unless, that's a problem for the OP's use-case, I intend to leave that restriction in place. A similar restriction also exists for graphics that contain transformations.

P.S. Hint as to how to use Texture is in my comment below. But you have to generate the plots correctly first, so I feel it is disqualified, if we are to treat the plots as given.

$\endgroup$
3
  • $\begingroup$ that is exactly how I generated the second plot. Don't focus on the y^2=a*x to much since it was just an example to generate a figure with. My real question is: "Given a set of 2D-plots (with not necessarilly a functional prescription), how can I stack these 2D plots in order to get a 3D image ?" $\endgroup$
    – Nick
    Commented Mar 11, 2015 at 15:56
  • $\begingroup$ @Nick, then here's another way that works for your example but won't work for you: Show[Table[Graphics3D[{Texture[Image@ContourPlot[y^2 == a*x, {x, 0, 2}, {y, -2, 2}, Frame -> False, ContourStyle -> Hue[(a - 1)/4, 1, 1, 1], ContourShading -> Opacity[0]]], EdgeForm[], Polygon[{{-π/2, -π/2, a}, {π/2, -π/2, a}, {π/2, π/2, a}, {-π/2, π/2, a}}, VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}, Lighting -> "Neutral"], {a, 1, 5, 0.5}]] :) Well, it's a bit slow anyway. $\endgroup$
    – Michael E2
    Commented Mar 11, 2015 at 16:23
  • $\begingroup$ Depending on whether any exact numbers or constants were present, using _?NumericQ might be robust. $\endgroup$
    – Yves Klett
    Commented Jun 19, 2015 at 11:20
12
$\begingroup$

A method of assembling 2d contour plots ...

 Show[Table[
     Graphics3D@
         First@Cases[
            Normal@ContourPlot[y^2 == a*x, {x, 0, 2}, {y, -2, 2}, 
                  Frame -> False], 
                      Line[x_] :> {Hue[(a - 1)/4], Line[Append[#, a] & /@ x]}, 
                      Infinity], {a, 1, 5, .5}] ,PlotRange->All]

enter image description here

$\endgroup$
2
  • $\begingroup$ Well, george, it's a bit funny that you correctly surmised the OP's intention from the the first, but (so far) have accumulated the fewest upvotes. Ah, the whimsical nature of SE! Anyway, +1 for dead heat (so far). $\endgroup$
    – Michael E2
    Commented Mar 11, 2015 at 16:43
  • $\begingroup$ @george2079, that's already a nice way to go! How would I need to do this if I were given a set of 2D plots, where each 2D slice depends on a parameter a ? I want the a-axis to be the extra z-axis in which I stack my 2D results. My question comes from the fact that for future calculations my 2D plots will be generated by a general calculation (minimalization proces) and that the results will be stacked as for the example. $\endgroup$
    – Nick
    Commented Mar 12, 2015 at 10:56
8
$\begingroup$

A quick one based on your phase diagram context, where bg contains the color of your 2D planes:

g = Table[ParametricPlot3D[{y^2/a, y, a}, {y, -2, 2}, 
PlotStyle -> Hue[(a*2 - 1)/10]], {a, 1, 5, 1}];

bg = Table[ContourPlot3D[z == a, {x, -4, 6}, {y, -4, 4}, {z, .8, 5.2}, 
Mesh -> None, ContourStyle -> Directive[Hue[1 - (a*2 - 1)/10], Opacity[0.3]]], 
{a, 1, 5, 1}];

Show[g, bg, PlotRange -> {{0, 4}, {-2, 2}, {0.4, 5.2}}]

$\endgroup$
4
  • $\begingroup$ That's indeed similar to how I generated the second picture. The is not what I'm looking for exactly ... $\endgroup$
    – Nick
    Commented Mar 11, 2015 at 16:02
  • $\begingroup$ @Nick I made some changes according to your phase diagram context. Is this what you want? $\endgroup$ Commented Mar 11, 2015 at 16:43
  • $\begingroup$ the answer is really nice, but the problem is that you already start from a parametric 3D plot. What I am asking is: "Given a set of 2D plots", where each 2D slice is determined by a paramter a, how do I combine them into a 3D plot with an additional axis a. The example that I have given was with the function y^2=a*x, but for practical purposes I'd need a general method since my future 2D plots will just be a collection of x and y values. $\endgroup$
    – Nick
    Commented Mar 12, 2015 at 10:53
  • $\begingroup$ @Nick If you only care about the final output, you could, in theory, put the data of your 2D slices in a list and replace g=Table[...] with g=ListPlot3D[...] in my answer. It's not exactly stacking 2D plots but the end result may look the same. For example, one way to get the data from Plot[...] is here. $\endgroup$ Commented Mar 12, 2015 at 11:27
3
$\begingroup$

You can specify the setting for the option Mesh to include graphics directives:

ContourPlot3D[y^2 == a*x, {x, 0, 2}, {y, -2, 2}, {a, 0.9, 5.1}, 
 MeshFunctions -> {#3 &}, Mesh -> {Table[{a, Hue[(a - 1)/4]}, {a, 1, 5, 0.5}]}, 
 ContourStyle -> None, BoundaryStyle -> None, BaseStyle -> Thick]

enter image description here

$\endgroup$
1
$\begingroup$

Using SliceContourPlot3D:

cols = Reverse@(Hue[Rescale[1 - #/5, {0, 1}]] & /@ Range[1, 5, 1/2])

plot = SliceContourPlot3D[y^2 - x #
      , {"ZStackedPlanes", {#}}
      , {x, 0, 2}, {y, -2, 2}, {z, 1, 5}
      , Contours -> 1
      , ContourShading -> Opacity[0.2, Hue[Rescale[1 - #/5, {0, 1}]]]
      , BoundaryStyle -> Hue[Rescale[1 - #/5, {0, 1}]]
      , ContourStyle -> {Directive[Thick, 
         Hue[Rescale[1 - #/5, {0, 1}]]]}
      , SphericalRegion -> True
      ] & /@ Range[1, 5, 1/2] //
   Show[#
     , AxesLabel -> {"x", "y", "a"}
     , AxesEdge -> {{-1, 0}, {1, 0}, {-1, -1}}
     ] &;
Legended[plot,
 Placed[SwatchLegend[cols, Reverse@Range[1, 5, 1/2]
   , LegendLabel -> Style["a", Bold, 12]
   , LegendLayout -> "Column"
   , LegendFunction -> "Frame"
   ], After]
 ]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.