Group Abstract Group Abstract

Message Boards Message Boards

Can I get a tip on how to optimize this code to render graphics faster?

GROUPS:
Hi All:
I'm working on a demonstration for my Calculus class on Volumes, with washers and cylindrical shells.

The code is below, and the main problem I'm having is when I display the simultaneous cylinders (Shell stack), the graphics slow WAY down.  I know that this is an intensive calculation, but I feel that the inclusion of this command in the code has slowed everything else down as well, even the Manipulate variables that don't involve the cylinders.

In particular the "cylStack" list seems to be causing the trouble.

Thanks for any help -- code is below.

Rob
 Manipulate[
  f[x_] := 1/4 x^4;
  g[x_] := 2 x;
 
  (* Defining the function plots *)
 
  fBound = ParametricPlot3D[{{x, 0, f[x]}, {-x, 0, f[x]}}, {x, 0, 2},
    PlotStyle -> {Thick, Directive[Dashed, Gray]}];
 
gBound =
  ParametricPlot3D[{{x, 0, g[x]}, {-x, 0, g[x]}}, {x, 0, 2},
   PlotStyle -> {Thick, Directive[Dashed, Gray]}];

(* Lines for orientation *)

hLine = Graphics3D[{Red, Thick,
    Line[{{1/2 wpos, 0, wpos}, {(4 wpos)^(1/4), 0, wpos}}]}];

vLine = Graphics3D[{Red, Thick,
    Line[{{cpos, 0, f[cpos]}, {cpos, 0, g[cpos]}}]}];

(* Lines for Axes *)

axesLine =
  Graphics3D[{{Line[{{-2, 0, 0}, {2, 0, 0}}],
     Line[{{0, 0, -1}, {0, 0, 4}}]}}];

(* Fill for the region *)
fill = Graphics3D[{
    EdgeForm[None], Blue, Opacity[.4],
    Polygon[Table[{n, 0, f[n]}, {n, 0.01, 2, .01}]
     ]}];

(* Defining the Slices *)

washPlot =
  RevolutionPlot3D[
   wpos, {t, 1/2 wpos, (4 wpos)^(1/4)}, {\[Theta], 0, \[Theta]max},
   Mesh -> None, PerformanceGoal :> "Quality"];

cylPlot =
  RevolutionPlot3D[{cpos, t}, {t, f[cpos], g[cpos]}, {\[Theta],
    0, \[Theta]max}, Mesh -> None, PerformanceGoal :> "Quality",
   PlotStyle -> Opacity[.6]];

(* Stacks *)

washStack =
  Table[RevolutionPlot3D[n, {t, 1/2 n, (4 n)^(1/4)}, Mesh -> None,
    PlotStyle -> Opacity[.5],
    BoundaryStyle -> RGBColor[.3, .2, .2, .5]], {n, .1, 3.9, .2}];

cylStack =
  Table[RevolutionPlot3D[{n, t}, {t, f[n], g[n]}, Mesh -> None,
    PlotStyle -> Opacity[.4],
    BoundaryStyle -> RGBColor[.3, 0, .4, .5]], {n, .1, 1.9, .1}] ;


(* For Display *)

Show[fBound, gBound, axesLine, fill,
  If[slc == 0, {hLine, washPlot}, {vLine, cylPlot}],
  If[wstk, washStack, {}],
  If[cstk, cylStack, {}],
  (* Global Properties for the SHOW Plot *)
 
  ViewPoint -> {0, -80, 12}, PlotRange -> {{-2, 2}, {-2, 2}, {-1, 4}},
   SphericalRegion -> True, Axes -> False, Boxed -> False,
  ViewAngle -> .013
  ],

(* Manipulate Controls *)
{{slc, 0,
   "Slice Orientation"}, {0 -> "Horizontal", 1 -> "Vertical"}},
{{wpos, 2, "Horizontal Slice Position"}, .01, 3.99},
{{cpos, 1, "Vertical Slice Position"}, .01, 1.99}, Delimiter,
{{\[Theta]max, .01, "Revolution Angle"}, .01, 2 Pi}, Delimiter,
{{wstk, False, "Show Washer Stack"}, {True, False}},
{{cstk, False, "Show Shell Stack"}, {True, False}},
ControlPlacement -> Left,
TrackedSymbols -> {\[Theta]max, wpos, cpos, slc, wstk, cstk}
]
POSTED BY: Rob Holman
Answer
6 months ago
Try to calculate fBound and gBound outside the Manipulate, so it doesn't get reevaluated every time.
POSTED BY: Sander Huisman
Answer
6 months ago
Gave that a shot, and there didn't seem to be much improvement.

My main point of confusion is why the inclusion of the stacks (washStack and cylStack) makes all of the other variables lag as well.  With those removed from the program, the image changes almost simultaneously with the drag of the slider.  With the stacks included, ALL of the manipulate variables start lagging.
POSTED BY: Rob Holman
Answer
6 months ago
I moved f, g, fBound, gBound, washStack, and cylStack out of the Manipulate...  and that helped a lot.

Your suggestion that the program was recalculating every time makes a lot of sense, Sander.  Thank you!   Once I put the intense computations (the stacks) outside of the Manipulate command, the effect on the other variables vanished.

However, the graphics for the cylinder stack still are VERY slow to respond when I try to grab the graphic and move it around to view from different angles.  Other than change the PerformanceGoal to "Speed", which degrades the image to a quality I find unusable, is there anything else I can try in order to improve the lag?

Thanks for all the help!

Rob
POSTED BY: Rob Holman
Answer
6 months ago
Setting the options  PlotPoints -> {2, 60}, MaxRecursion -> 0  on  cylStack  and  washStack  reduces their size by a factor of more than 10.  This will speed things up.

It also help if you get rid of more global symbols (e.g  hLine,  vLine,   washPlot,  cylPlot).  When they are changed inside  Manipulate,  the change causes a second update, which makes the responsiveness twice as bad.  I used  With  to make them local.

Code dump:
 f[x_] := 1/4 x^4;
 g[x_] := 2 x;
 (*Defining the function plots*)
 fBound = ParametricPlot3D[{{x, 0, f[x]}, {-x, 0, f[x]}}, {x, 0, 2},
    PlotStyle -> {Thick, Directive[Dashed, Gray]}];
 gBound = ParametricPlot3D[{{x, 0, g[x]}, {-x, 0, g[x]}}, {x, 0, 2},
    PlotStyle -> {Thick, Directive[Dashed, Gray]}];
 (*Lines for Axes*)
 axesLine =
  Graphics3D[{{Line[{{-2, 0, 0}, {2, 0, 0}}],
     Line[{{0, 0, -1}, {0, 0, 4}}]}}];
(*Fill for the region*)
fill = Graphics3D[{EdgeForm[None], Blue, Opacity[.4],
    Polygon[Table[{n, 0, f[n]}, {n, 0.01, 2, .01}]]}];
(*Stacks*)washStack =
  Table[RevolutionPlot3D[n, {t, 1/2 n, (4 n)^(1/4)}, Mesh -> None,
    PlotPoints -> {2, 60}, MaxRecursion -> 0,
    PlotStyle -> Opacity[.5],
    BoundaryStyle -> RGBColor[.3, .2, .2, .5]], {n, .1, 3.9, .2}];
cylStack =
  Table[RevolutionPlot3D[{n, t}, {t, f[n], g[n]},
    Mesh -> None, PlotPoints -> {2, 60}, MaxRecursion -> 0,
    PlotStyle -> Opacity[.4],
    BoundaryStyle -> RGBColor[.3, 0, .4, .5]], {n, .1, 1.9, .1}];


Manipulate[
(*Lines for orientation*)
With[{hLine =
    Graphics3D[{Red, Thick,
      Line[{{1/2 wpos, 0, wpos}, {(4 wpos)^(1/4), 0, wpos}}]}],
   vLine =
    Graphics3D[{Red, Thick,
      Line[{{cpos, 0, f[cpos]}, {cpos, 0, g[cpos]}}]}],
   (*Defining the Slices*)
   washPlot =
    RevolutionPlot3D[
     wpos, {t, 1/2 wpos, (4 wpos)^(1/4)}, {\[Theta], 0, \[Theta]max},
     PlotPoints -> {2, 60}, MaxRecursion -> 0, Mesh -> None, PerformanceGoal :> "Quality"],
   cylPlot =
    RevolutionPlot3D[{cpos, t}, {t, f[cpos], g[cpos]}, {\[Theta],
      0, \[Theta]max}, PlotPoints -> {2, 60}, MaxRecursion -> 0, Mesh -> None, PerformanceGoal :> "Quality",
     PlotStyle -> Opacity[.6]]},
 
  (*For Display*)
 
  Show[fBound, gBound, axesLine, fill,
   If[slc == 0, {hLine, washPlot}, {vLine, cylPlot}],
   If[wstk, washStack, {}], If[cstk, cylStack, {}],
   (*Global Properties for the SHOW Plot*)ViewPoint -> {0, -80, 12},
   PlotRange -> {{-2, 2}, {-2, 2}, {-1, 4}}, SphericalRegion -> True,
   Axes -> False, Boxed -> False, ViewAngle -> .013]
  ],

(*Manipulate Controls*){{slc, 0,
   "Slice Orientation"}, {0 -> "Horizontal",
   1 -> "Vertical"}}, {{wpos, 2, "Horizontal Slice Position"}, .01,
  3.99}, {{cpos, 1, "Vertical Slice Position"}, .01,
  1.99}, Delimiter, {{\[Theta]max, .01, "Revolution Angle"}, .01,
  2 Pi}, Delimiter, {{wstk, False, "Show Washer Stack"}, {True,
   False}}, {{cstk, False, "Show Shell Stack"}, {True, False}},
ControlPlacement -> Left,
TrackedSymbols -> {\[Theta]max, wpos, cpos, slc, wstk, cstk}
]
POSTED BY: Michael Rogers
Answer
6 months ago
Michael:

This is fantastic!  Thank you so much -- I still have a lot to learn about the proper structuring of a program, so I'll certainly be studying the adjustments you made and putting them to good use in the future.

Thanks again!
POSTED BY: Rob Holman
Answer
6 months ago
Michael:

As I was studying your revisions, I noticed that you introduce the variables \max, wpos, and cpos at the front of the Manipulate command, and that these are the very same variables that are necessary within the With command.  I'm curious to know what the effect or benefit of this "early introduction" is -- out of curiosity I removed those variables from the beginning of the Manipulate and ran the program again, and I noticed no discernible difference in the result.

Thanks for all of your help,

Rob
POSTED BY: Rob Holman
Answer
6 months ago
Rob,

Sorry about that.  I was playing around and I should have removed them, which I've now done.  I've forgotten exactly why I put them in there.  (There can be reasons for doing so.  If it's the only place a variable shows up in the body of the  Manipulate,  then it causes the body to be updated whenever the variable is changed, because the code appears to depend on the variable.  Those variables  θmax, wpos, cpos  appear inside the  With  statement, so it's redundant to place them at the beginning of the  Manipulate.  It was probably when I trying to take as much code out of the  Manipulate  as possible and put it in an  Initialization  option.)

    - Michael
POSTED BY: Michael Rogers
Answer
6 months ago