RE: How to set y always greater than or equal to x for a function?
- To: mathgroup at smc.vnet.net
- Subject: [mg46591] RE: [mg46569] How to set y always greater than or equal to x for a function?
- From: "David Park" <djmp at earthlink.net>
- Date: Tue, 24 Feb 2004 21:04:50 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
Albert, I think this is an interesting plotting problem whose solution is not totally obvious. If you are just beginning to learn Mathematica, then it is probably not the first problem to tackle. Plot3D[Sqrt[y - x], {x, -100, 100}, {y, -100, 100}]; gives warning messages and a jagged edge to the surface. We could define a function f[x_, y_] := If[y > x, Sqrt[y - x], 0] Then Plot3D[f[x, y], {x, -100, 100}, {y, -100, 100}]; works more or less. But it has the extra xy-plane surface, which is not part of the surface you are specifying. A few years ago I learned the following trick from MathGroup. (I can't remember exactly who posted it.) Generate the plot above and then throw out all points that have y <= x. plot1 = Graphics3D@ Plot3D[f[x, y], {x, -100, 100}, {y, -100, 100}, DisplayFunction -> Identity]; plot2 = MapAt[# /. {x_?NumberQ, y_?NumberQ, z_?NumberQ} /; y <= x -> Sequence[] &, plot1, 1]; We had to convert the plot from SurfaceGraphics to Graphics3D. We had to map our function onto the first part of plot1. The first part contains all the primitive graphics for the surface. Any point in a Polygon for which y <=x gets replaced by Sequence[], which effectly gets rid of it. We then Show the new plot. Show[plot2, DisplayFunction -> $DisplayFunction]; That gives a pretty good representation of the surface. The DrawGraphics package at my web site gives some other techniques for handling plotting problems of this type. One of its advantages is that it automatically extracts the primitive graphics from any plot and it is then easy to manipulate or combine the various elements. Needs["DrawGraphics`DrawingMaster`"] The following implements the same trick as above. Module[{g}, g = Draw3D[f[x, y], {x, -100, 100}, {y, -100, 100}]; Draw3DItems[ {g /. {x_?NumberQ, y_?NumberQ, z_?NumberQ} /; y <= x -> Sequence[]}, BoxRatios -> {1, 1, 1/2}, Axes -> True]]; Another method is to reparametrize the surface. If we were going to integrate a two variable function we could use Integrate[f[x,y],{x,-100,100},{y,x,100}]. The second iterator depends on x. But we can't directly do that when plotting surfaces. DrawGraphics has the command IteratorSubstitution[{y, Sqrt[y - x]}, {y, x, 100}] {{(-w)*(-100 + x) + x, Sqrt[(-w)*(-100 + x)]}, {w, 0, 1}} It reparametrizes y and Sqrt[y-x] for {y,x,100} in terms of x and w. w has the fixed iterator {w,0,1}. We can then plot this new function and then use DrawingTransform3D to get back from the xw-plane to the xy-plane. Draw3DItems[ {Draw3D[Sqrt[(-w)*(-100 + x)], {x, -100, 100}, {w, 0, 1}] /. DrawingTransform3D[#1 & , (-#2)*(-100 + #1) + #1 & , #3 & ]}, BoxRatios -> {1, 1, 1/2}, Axes -> True, Background -> Linen, ImageSize -> 450]; But this isn't too nice for this particular case because the polygons are crimed together at one corner. Another idea is to plot the function Sqrt[y], where we can use fixed ranges and then rotate it by 45 degrees. I plot it in two sections to get a better representation of the rising section. Draw3DItems[ {{Draw3D[Sqrt[y], {x, -150, 150}, {y, 0, 2}, PlotPoints -> {25, 2}], Draw3D[Sqrt[y], {x, -150, 150}, {y, 2, 150}, PlotPoints -> 25]} // UseRotateShape[-45°, 0, 0]}, BoxRatios -> {1, 1, 1/2}, PlotRange -> {{-100, 100}1.01, {-100, 100}1.01, {-0.1, 15.1}}, Axes -> True, Background -> Linen, ImageSize -> 450]; This is probably a little nicer than the non DrawGraphics plot because the "mesh" lines are either level, or the sqrt curves. As an extra, here is the same surface combined with -Sqrt[y-x] and then spun around for better viewing. g is just the primitive graphics for the surface we plotted above. We draw it and then we draw it again with the z component reversed. plot3 = Module[{g}, g = {Draw3D[Sqrt[y], {x, -150, 150}, {y, 0, 2}, PlotPoints -> {25, 2}], Draw3D[Sqrt[y], {x, -150, 150}, {y, 2, 150}, PlotPoints -> 25]} // UseRotateShape[-45°, 0, 0]; Draw3DItems[ {g, g /. DrawingTransform3D[#1 &, #2 &, -#3 &]}, BoxRatios -> {1, 1, 1}, Boxed -> False, PlotRange -> {{-100, 100}1.01, {-100, 100}1.01, {-12.1, 12.1}}, Background -> Linen, ViewPoint -> {1.779, -2.844, 0.447}, ImageSize -> 450]]; SpinShow[plot3] SelectionMove[EvaluationNotebook[], All, GeneratedCell] FrontEndTokenExecute["OpenCloseGroup"]; Pause[0.5]; FrontEndExecute[{FrontEnd`SelectionAnimate[200, AnimationDisplayTime -> 0.1, AnimationDirection -> Forward]}] David Park djmp at earthlink.net http://home.earthlink.net/~djmp/ From: Albert Franco [mailto:francoatnsuok at earthlink.net] To: mathgroup at smc.vnet.net I recently purchased Mathematica 5.0, and I am in the process of learning how to take advantage of it's many features. This is an example of one line I would like to calculate in Mathematica: Plot3D[Sqrt[y-x],{x,-100,100},{y,-100,100}]; How can I best edit this line to make y always greater than or equal to x during calculation so the program doesn't try to take the square root of a negative number? Any help will be appreciated. Albert Franco