Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

My goal is to use ColorFunction to color a cylinder based on the $z$ value of a separate Plot3D. I'm not sure if I am making a mathematical error somewhere or if I am just messing up some snippet of the following code.

a = Pi;
b = 2;
f[x_, y_] = y;
u[x_, y_, t_] = -((8 E^(-((\[Pi]^2 t)/20)) (2 - \[Pi]) Cos[(\[Pi] y)/4])/\[Pi]^2) - 
   (8 E^(-((\[Pi]^2 t)/5)) (2 + 3 \[Pi]) Cos[(3 \[Pi] y)/4])/(9 \[Pi]^2) - 
   (8 E^(-((9 \[Pi]^2 t)/20)) (2 - 5 \[Pi]) Cos[(5 \[Pi] y)/4])/(25 \[Pi]^2);

Table[ContourPlot[u[x, y, t], {x, -a, a}, {y, 0, b}, 
   ColorFunction -> ColorData["TemperatureMap"], 
   Contours -> 8], {t, {0, .1, .3, .5, 1, 2, 3, 4}}]

enter image description here

Now, I want to wrap each contour plot onto a cylinder by gluing the $x=-a$ edge to the $x=a$ edge; the bottom of the cylinder is then at $y=0$ and the top at $y=b$.

 Table[ParametricPlot3D[{Cos[theta], Sin[theta], rho}, {theta, -Pi, Pi}, {rho, 0, 2},  
    AxesLabel -> {x, y, z}, ColorFunctionScaling -> False, 
    ColorFunction -> Function[{x, y, z, theta, rho}, 
    ColorData["TemperatureMap"][u[x, rho, t]]],
    Mesh -> 8, MeshFunctions -> {Function[{x, y, z, theta, rho}, 
    f[Cos[theta], rho]]}, ViewPoint -> {-2.3, 0.77, -2}, 
    ViewVertical -> {-0.08, 1, -0.06}], 
    {t, {0, .1, .3, .5, 1, 2, 3, 4}}]

enter image description here

This is clearly not correct based on what I am after. Where am I going wrong?

I tried turning ColorFunctionScaling off and on with no luck. I also tried replacing that middle snippet dealing with the coloring with

ColorFunctionScaling -> False, 
ColorFunction -> Function[{x, y, z, theta, rho}, 
ColorData["TemperatureMap"][Rescale[u[Cos[theta], rho, t], {0,2}]]]

where a Plot3D shows $u(x,y,t)$ ranges over (about) $[0,2]$. I suspect the solution lies in some tweaking of this part.

share|improve this question
    
Could you pls add the function f? –  kguler Nov 16 '12 at 4:25
    
Done, sorry about that. –  JohnD Nov 16 '12 at 4:28
    
Looking at the documentation for ColorFunction I thought the only arguments allowed to pass to it in a ParametricPlot3D were x, y, z, and u where these are the three spacial variables of ParametricPlot3D together with the parameter variable u. Is that not correct? (I wish the documentation explained this better.) –  JohnD Nov 16 '12 at 4:34

3 Answers 3

up vote 2 down vote accepted

You can get the colors from the 2D contour plots and use them as the setting for MeshShading:

 tt = {0, .1, .3, .5, 1, 2, 3, 4}; 
 cps = Table[ContourPlot[u[x, y, t], {x, -a, a}, {y, 0, b}, 
   ColorFunction -> ColorData["TemperatureMap"], Contours -> 8],  {t, tt}];
 colors = Cases[cps[[#]], _RGBColor, Infinity] & /@ Range[8];

Then

Grid[Partition[Table[ParametricPlot3D[{Cos[theta], Sin[theta], rho}, 
       {theta, -Pi,  Pi}, {rho, 0, 2},
   Mesh -> 8,
   MeshFunctions -> {Function[{x, y, z, theta, rho}, u[x, z, tt[[i]]]]},
   MeshShading -> colors[[i]],
   ColorFunction -> Function[{x, y, z, theta, rho},
      ColorData["TemperatureMap"][u[x, z, tt[[i]]]]],
   AxesLabel -> {x, y, z}], {i, Range[8]}], 4]]

gives

enter image description here

share|improve this answer
    
Thanks for this answer too since I did not know how to pull the colors of a ContourPlot to then use as MeshShading. –  JohnD Nov 18 '12 at 22:29

Main thing to know is that for ColorData["TemperatureMap"][f[x]] you must have 0 < f < 1. What ColorFunctionScaling does - it rescales range x, and you need to rescale domain f.

I will consider a simplified case of your problem and you can generalize. Let's take t = 0.5 Stripping your function u of unneeded variables, you have:

u[y_,t_]=(-8*(2 - Pi)*Cos[(Pi*y)/4])/(E^((Pi^2*t)/20)*Pi^2) - 
 (8*(2 + 3*Pi)*Cos[(3*Pi*y)/4])/(9*E^((Pi^2*t)/5)*Pi^2) - 
 (8*(2 - 5*Pi)*Cos[(5*Pi*y)/4])/(25*E^((9*Pi^2*t)/20)*Pi^2)

Let's plot its original and re-scaled forms:

{min, max} = {NMinValue[#, y], NMaxValue[#, y]} &@{u[y, .5], 0 < y < 2}

{1.29488*10^-16, 0.789722}

Plot[{u[z, .5], (u[z, .5] - min)/(max - min)}, {z, 0, 2}, PlotRange -> All, Filling -> 0]

plot of original and rescaled coloring function

You can see the difference. Now, the correct cylinder for t = 0.5 is set up like this - and you can see exact correspondence to your rectangle pictures:

GraphicsRow[{

ParametricPlot3D[{Cos[theta], Sin[theta], z}, {theta, -Pi, Pi}, {z, 0, 2}, 
AxesLabel -> {x, y, z}, ColorFunctionScaling -> False, 
ColorFunction -> Function[{x, y, z, m, n}, 
             ColorData["TemperatureMap"][Rescale[u[z, .5], {min, max}]]], 
Mesh -> 8,  MeshFunctions -> 
     Function[{x, y, z, m, n}, Rescale[u[z, .5], {min, max}]]],

  ContourPlot[u[y, .5], {x, -Pi, Pi}, {y, 0, 2}, 
   ColorFunction -> ColorData["TemperatureMap"], Contours -> 8]}]

properly colored cylinder with contour plot

share|improve this answer
    
NMaxValue[] might be more convenient to use here... also Rescale[]. –  J. M. Nov 16 '12 at 9:32
    
@J.M. NMaxValue - yes, but not sure about Rescale - it acts on lists, not functions. What did you have in mind? –  Vitaliy Kaurov Nov 16 '12 at 9:42
    
Something like ColorData["TemperatureMap"][Rescale[u[z, 0.5], {0, max}]] was what I used. –  J. M. Nov 16 '12 at 9:51
    
@J.M. Yes, this makes sense, updated. –  Vitaliy Kaurov Nov 16 '12 at 12:24

I figured that since the question's been answered anyway, I'd illustrate the Texture[] alternative, which completely avoids the rigamarole of having to find the extrema of the coloring function:

a = π; b = 2;
f[x_, y_] := y;
u[x_, y_, t_] := -((8 E^(-((π^2 t)/20)) (2 - π) Cos[(π y)/4])/π^2) -
                 (8 E^(-((π^2 t)/5)) (2 + 3 π) Cos[(3 π y)/4])/(9 π^2) -
                 (8 E^(-((9 π^2 t)/20)) (2 - 5 π) Cos[(5 π y)/4])/(25 π^2);

tex = With[{t = 0.5},
           Image[ContourPlot[u[x, y, t], {x, -a, a}, {y, 0, b}, 
                             AspectRatio -> Automatic, ColorFunction -> "TemperatureMap", 
                             Contours -> 8, Frame -> None, ImagePadding -> None, 
                             PlotRange -> All, PlotRangePadding -> None], 
                 ImageResolution -> 256]];

ParametricPlot3D[{Cos[θ], Sin[θ], ρ}, {θ, -a, a}, {ρ, 0, b},
                 AxesLabel -> {x, y, z}, Lighting -> "Neutral", 
                 Mesh -> None, PlotStyle -> Texture[tex], 
                 ViewPoint -> {-2.3, 0.77, -2}, ViewVertical -> {-0.08, 1, -0.06}]

cylinder with texture

I'll leave the generalization as an exercise for the interested reader.

share|improve this answer
    
Very nice. I too like that it avoids the extrema issue. –  JohnD Nov 19 '12 at 0:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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