# Plot[f,{x, xmin, xmax}], where xmax is not a const

I have a graph of the function, as in the picture. Function can be set manually, but after a certain value, it is 0. Could I find this value to put it instead of xmax=1 in Plot in order to avoid useless tail f = 0 and make picture more readable?

The code

Show
[
ListPlot[Qp], PlotRange -> All,AxesLabel ->{"p,cars/m","Q,cars/s"}],
Plot[
{f[p]},
{p, 0, 1},
AxesLabel -> {"p, cars/m", ""}, PlotStyle -> {Red, Thick}
],
ImageSize -> plotWidth
],


P.S.

 Qp = Transpose@{p, Q};


where Q and p are arrays

P.SS. f[p] i get from InputField

• the 0.7 is explicitly in your expression, why don't you just use it? – george2079 Sep 8 '15 at 19:00
• This value of the function can be changed manually. After this immediately and dynamically changing the graph. Could you tell me,please, what can be done to change not only the graph, but also the scale – Mishin V. Sep 8 '15 at 19:36
• Have you tried using Dynamic to update the plot when the function is updated? – IPoiler Sep 8 '15 at 19:44

You may wish to consider a post-processing method. You would need to make sure that the starting value is enough to include at least the range you wish to plot, but you can trim the zero area with this:

fixit = Show[
MapAt[# /. Line[d_] :> Line[Join @@ Most @ SplitBy[d, Last@# == 0 &]] &, #, 1],
PlotRange -> Automatic] &;


For example:

p = Plot[Sin[x]*UnitBox[x/10], {x, 0, 10}]


p // fixit


To include the line segment that drops to zero you may use this modified function:

fixit2 = Show[
MapAt[# /. Line[d_] :>
Line[Join @@ MapAt[{First@#} &, SplitBy[d, Last@# == 0 &], -1]] &, #, 1],
PlotRange -> Automatic] &;


Test:

p // fixit2


• very nice,thanks a lot. now i have something like pastebin.com/u5TNGDHS but after i change the function, the graph doesn't change dynamically.it is possible to do somethong with it? – Mishin V. Sep 9 '15 at 11:58
• f[x_] :> If[p < 0.05, -6044p^3 + 231p^2 + 22.2222p, If[p < 0.09, -3755p^3 + 767p^2 - 48p + 1.91376, If[p <= 0.7, 1.672 (0.7 -p), 0]]] imgur.com/EOKZ3b0 imgur.com/urySEMq i change the value in last "if" p <= 0.7 from 0.7 to 0.6 or 0.3 and,as you can see, not only zero area trimmed. Did you mean it when sad "You would need to make sure that the starting value is enough to include at least the range you wish to plot"? – Mishin V. Sep 9 '15 at 13:02
• @Mishin By the way I think your function should be: f[p_] := If[p < 0.05, -6044 p^3 + 231 p^2 + 22.2222 p, If[p < 0.09, -3755 p^3 + 767 p^2 - 48 p + 1.91376, If[p <= 0.7, 1.672 (0.7 - p), 0]]]. My function appears to be working as I intended on your example. When you change the values as described you create an abrupt fall to zero, and my method does not include that "fall" as it were, just the point immediately before it. I presume you would like to include that last vertical line dropping to zero? I can do that I believe. – Mr.Wizard Sep 9 '15 at 19:48

## Random test function

I'm assuming all the functions to be considered are nonnegative, just as in the example.

SeedRandom[0];
data = Transpose[{
Range[0., 1., 1./40],
FoldList[
Max[0., Min[##]] &,
Reverse@Sort@RandomReal[{-0.65, 1}, {41}]
]
}];
f = Interpolation[data, InterpolationOrder -> 1];
Plot[f[x], {x, 0, 1}]


## First Method

Use EvaluationMonitor to find where the function hits zero:

Module[{plot, zerox},
{plot, zerox} =
Reap[Plot[f[x], {x, 0, 1},
EvaluationMonitor :> If[f[x] == 0, Sow[x]]]];
Show[plot, PlotRange -> {{0, Min[zerox]}, PlotRange[plot][[2]]}]
]


Or where it stops being zero:

Module[{plot, nonzerox},
{plot, nonzerox} =
Reap[Plot[f[x], {x, 0, 1},
EvaluationMonitor :> If[f[x] > 0, Sow[x]]]];
Show[plot, PlotRange -> {{0, Max[nonzerox]}, PlotRange[plot][[2]]}]
]


## Second Method

This resembles how one might think Plot would work: drawing the line from one end until it is time to stop. Here we interpolate the test function with NDSolve, using WhenEvent to stop the process when the function hits zero.

ListLinePlot@NDSolveValue[
{y[t] == f[t], x'[t] == 1, x[0] == 0,
WhenEvent[y[t] < 0, "StopIntegration"]},
y, {t, 0, 1}, PrecisionGoal -> 5, AccuracyGoal -> 5]


• thanks a lot. totally my fault, using both methods I encounter a problem how and where should i put ListPlot[Qp] to display it also. Could you give me any advice please. – Mishin V. Sep 9 '15 at 12:04
• Would the graph changed dynamically after i will change the function in inputfield? – Mishin V. Sep 9 '15 at 12:11
• @MishinV. You included a Manipulate image, but not code for it. It is not hard to make it work with Manipulate so that the plot updates dynamically, but, judging from other users' code on this site, the details of how to do it well depends on the code of each user. A simple example might or might not be helpful to you. What do you think? – Michael E2 Sep 9 '15 at 12:53
• I'm sorry, You are completely right. I'll try to deal with it on my own. – Mishin V. Sep 9 '15 at 13:01
• @MishinV. You could ask another question about getting the plot to dynamically update with Manipulate. (It's better than continually modifying this question, and better than trying to work it out in comments.) – Michael E2 Sep 9 '15 at 13:06

Not very robust ...

Panel[DynamicModule[{f = 1 - x^2 },
Column[{InputField[Dynamic[f]],
Dynamic[Plot[ f, {x, 0, x /. Quiet@Last@Maximize[{x, f > 0}, x]}]]}]]]


Plot[{f[p]}, {p, 0, 1}, AxesLabel -> {"p, cars/m", ""}, PlotRange ->
{{0, Evaluate[x /. FindRoot[f[x] == 0, {x, .1}]]}, {0, Automatic}}]