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.

I would like to create a plot whereby both the slider and the locator 'draw' the plot. In the following code, the locator & the slider act independently:

f[x_] := Sin[x];
Manipulate[With[{x0 = Clip[p[[1]], {0, 20}]}, Plot[f[x], {x, 0, t}, 
ImagePadding -> 20, PlotRange -> {{0, 20}, {-2, 2}}, LabelStyle -> (FontFamily -> 
"Ariel"), Epilog -> {PointSize[Large], Red, Tooltip[Point[#], #] &@{x0, f[x0]}}]], 
{t, 0.001, 20}, {{p, {0, 0}}, Locator, Appearance -> None}, AppearanceElements -> None]

I would like to get both to work together, so the slider 'draws' the plot, as does the locator when it is dragged. Here is an illustration of what I am trying to achieve:

enter image description here

share|improve this question
add comment

3 Answers 3

up vote 3 down vote accepted

I would link one of the controls to the other. Make one (t) update the other (p) inside Dyanmic. Make the other update the one inside the body of Manipulate. Then track the other (p). I chose to track p because creating a custom slider is easier than creating a custom locator.

f[x_] := Sin[x];
Manipulate[With[{x0 = Clip[p[[1]], {0.001, 20}]},
  t = x0;
  Plot[f[x], {x, 0, t}, ImagePadding -> 20, 
   PlotRange -> {{0, 20}, {-2, 2}}, 
   LabelStyle -> (FontFamily -> "Ariel"), 
   Epilog -> {PointSize[Large], Red, 
     Tooltip[Point[#], #] &@{x0, f[x0]}}]],
 {t, 0.001, 20,  Manipulator[Dynamic[t, (p[[1]] = t = #) &], ##2] &},
 {{p, {0, 0}}, Locator, Appearance -> None},
 AppearanceElements -> None, 
 TrackedSymbols :> {p}]

How to write custom controls is discussed in Advanced Manipulate Functionality. Custom controls are declared in a Manipulate by pure Functions, often used in the form ctrl[##] &. Manipulate passes several arguments to the control. The first argument is Dynamic[t], where t is the control's variable. The second argument is generally a List of the data that appears in the variable declaration (e.g. {0.001, 20} in the control for t). Any other arguments are usually options. We needed to override just the first argument with a custom Dynamic. The rest of the arguments, represented by ##2, are passed as is. In this case, one could use #2 instead of ##2; one could also explicitly pass {0.001, 20} and skip the # slots altogether.

The custom Dynamic links the slider to the locator: The locator's x coordinate is reset whenever the slider is moved. The link from the locator back to t is done in the body of the Manipulate by t = x0.

Finally, the way dynamic updating works can be subtle. If a symbol var is being tracked and the value of var is changed in the body of the Manipulate during an update, another update will be generated; this causes the body to be executed a again. (Sometimes this leads to infinite loops.) If t were a tracked symbol, then the Manipulate body would execute twice each time the control or locator was moved. (On the second evaluation, t is set to its old value, so a new update is not generated.) For this reason, I excluded it from being tracked by means of the TrackedSymbols option. The way it is now is that if the t slider is moved both t and p change values; the change in p causes an update and the graph is redrawn. And if p changes by clicking on the graph, an update is generated that changes t and redraws the graph.

share|improve this answer
    
(FontFamily -> "Ariel") –  belisarius Oct 25 '13 at 0:06
    
@belisarius "Ariel" looks different on a Mac and on Windows –  Michael E2 Oct 25 '13 at 0:32
    
@ Belisarius - you are quite right, it should be 'Arial' - silly mistake (although as Michael E2 says, Windows doesn't seem to mind!) –  martin Oct 25 '13 at 8:55
    
@ Michael E2, Many thanks - this works perfectly & does exactly what I was after - I am unsure about the implementation of the ## though - in the documentation, it says that ## stands for the sequence of all arguments - but I am not at all clear on what this implies. At the risk of sounding very naive, is this what helps tie the 2 controls to one another? –  martin Oct 25 '13 at 9:00
    
@belisarius Hehe, I did not catch the error with font name. There is an Ariel. :) –  Michael E2 Oct 25 '13 at 10:45
add comment

This a example when I start learning Mathematica.I hope it can help you.Good luck.

Manipulate[
         If[
            ini == pres,
            Graphics[
                    {PointSize[Medium], Red, Point[{ini, Sin[n ini]}]},
                     Axes -> True,
                     PlotRange -> {{ini, end + 1}, {-1.2, 1.2}},
                     AspectRatio -> Automatic
                    ],
         Plot[
             Sin[n x], {x, ini, pres}, 
             Epilog -> {PointSize[Medium], Red, Point[{pres, Sin[n pres]}]}, 
             PlotRange -> {{ini, end + 1}, {-1.2, 1.2}},
             AxesStyle -> Arrowheads[.02], 
             AxesLabel -> {Style["x", 18, Purple], Style["y", 18, Purple]}
             ]
          ],
        {{ini, 0, "startvalue"}, 
        ControlType -> InputField}, {{end, 2 Pi, "endvalue"}, 
        ControlType -> InputField}, {{n, 1, "freq"}, 1, 20, 1, 
        Appearance -> "Labeled"}, {{pres, Pi, "current endvalue"}, ini, end,
        Appearance -> "Labeled"}
    ]

enter image description here

share|improve this answer
    
@ Tangshutao, Many thanks for your answer - you have added some extra things that I will definitely study :-) –  martin Oct 25 '13 at 8:51
    
@martin,Dear martin,Thanks.And I can also learn more from your question.We should learn each other.:-) –  Tangshutao Oct 25 '13 at 13:58
add comment

In your previous question we connected the slider to the locator.

Now we change the plot domain: Instead of plotting from 0 all the way to 20 we only plot up to x0. We don't want the plotted region to change, so we use the PlotRange option (see the documentation center)

f[x_] := Sin[x];
(*External variables for remembering previous values*)
xSave = 0;
pSave = {0, 0};
Manipulate[
  (*compare values and handle changes appropriately*)
  If[xx != xSave, xSave = xx; p[[1]] = xx;];
  If[p != pSave, pSave = p; xx = p[[1]];];
  (*The manipulated object*)
  With[{x0 = Clip[p[[1]], {0.01, 20}]}, 
    Plot[f[x],
     (* we only plot up to the locator *)
     {x, 0, x0},
     (* but we display the entire domain *)
     PlotRange -> {{0, 20}, {-1, 1}}, 
     Epilog -> {PointSize[Large], Red, 
       Tooltip[Point[#], #] &@{x0, f[x0]}}
  ]],(*The controls*)
  {{xx, 0.01, "x"}, 0.01, 20},
  {{p, {0.01, 0}}, Locator, Appearance -> None}, 
  AppearanceElements -> None]
share|improve this answer
    
@ Timothy Wofford, Many thanks for your reply & for building on my previous question - works well (though the position of the number '10' on the x-axis is unstable at beginning & end of plot - is that something to do with x value being 0 rather than 0.001?) –  martin Oct 25 '13 at 8:50
    
The 0.01 in my code or 0.001 in Michael's code is because the plot has range {x,0,x0} and x0 cannot be equal to zero. I do not understand what you mean by an unstable position. –  Timothy Wofford Oct 25 '13 at 10:54
    
@ Timothy Wofford, It just flickers a bit - no problem though - I see what you mean about the 0.001 :-) –  martin Oct 25 '13 at 11:46
add comment

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.