0
$\begingroup$

This question already has an answer here:

As I said before for the time being, I don't want to use Mathematica as a programming tool. I'm just using it as a calculater to compute integrals, solve equations, etc because of its support of symbolic math.
So my question is not about adding zooming and panning capability to your code

As you know in 3D graphics (as far as I know graphics that are created by Plot3D function) we can use:

  • Click + Drag ---> Rotate
  • Alt + Click + Drag ---> Zoom in and out
  • Shift+Click+Drag ---> Pan

but for 2D graphics (as far as I know graphics that are created by Plot function) we don't have such capability.

I searched a bit on the net and in this site and found out that there are no built in plot manipulating interface in mathematica and I should use this code to be able to pan and zoom on 2D plots that I have created in notebook.
But I don't know how to use a certain piece of code and call a function in mathematica. I'm just starting to learn, so please pardon me if it's so trivial.

For example suppose that I have created this plot and now I want to be able to pan and zoom on it. What should I do?

Manipulate[
 Plot[PDF[VonMisesDistribution[μ, κ], x], {x, -Pi + μ, 
   Pi + μ}, PlotRange -> {{-5, 5}, {0, 20}}], {{μ, 0}, -5, 
  5}, {{κ, 5}, 0, 1000}]
$\endgroup$

marked as duplicate by Yves Klett, MarcoB, C. E., yohbs, Öskå Sep 16 '15 at 17:17

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ What do you mean by "I don't know how to use a certain piece of code"? Are you talking about a specific piece of code or code in general? I assume by now you should have figured out how to run code. As to the specific question at the bottom of the post: just change the numbers in the x range to pan and the numbers in the PlotRange option to zoom. You can make those numbers parameters in the Manipulate as well. $\endgroup$ – Sjoerd C. de Vries Sep 15 '15 at 21:26
  • 5
    $\begingroup$ @SjoerdC.deVries changing the numbers of PlotRange is one way. But I want to know if there is any built-in way as in Plot3D, some GUI interface that enables you to pan. The code here seems to be able to add this GUI to a 2D graphic. about the sentence I don't know how to use a certain piece of code and call a function in mathematica.: My purpose is that for example in C++ we have object oriented programming. We use 3rd party libraries and are not aware of their implementation. We are just $\endgroup$ – Sepideh Abadpour Sep 15 '15 at 21:45
  • $\begingroup$ @SjoerdC.deVries familiar with the interface of the function in the library. We call the functions in our code, pass parameters to them and get the output and use in our code. or in matlab if I want to use this ready function in my code, I just put the M-file of it in the same directory that my code is running. And I just call the functions in my code. My purpose is if we consider this code a ready package, how should $\endgroup$ – Sepideh Abadpour Sep 15 '15 at 21:51
  • $\begingroup$ I use that ready functions in my code? $\endgroup$ – Sepideh Abadpour Sep 15 '15 at 21:52
  • $\begingroup$ Just run the PlotExplorer code in that answer and you can use the PlotExplorer function as shown as in the examples in the post. The libraries you are looking for are called packages in Mathematica. You can read about them here. $\endgroup$ – Sjoerd C. de Vries Sep 15 '15 at 21:59
2
$\begingroup$
Manipulate[
 Pane[
  Plot[Sin[x], {x, -10, 10}],
  ImageSize -> {300, 200},
  Scrollbars -> True,
  ScrollPosition -> {a, b}],
 {a, 10, 200},
 {b, 10, 200}]
$\endgroup$
  • $\begingroup$ Very nice. I wasn't aware of the Srollbars option. From this I can see that a "zoom" can also be added: Manipulate[ Pane[Plot[Sin[x], {x, -10, 10}, ImageSize -> zoom {600, 400}], ImageSize -> {300, 200}, Scrollbars -> True], {{zoom, 1, "Zoom"}, 0.1, 10}] $\endgroup$ – JimB Sep 16 '15 at 13:38
1
$\begingroup$

The answer by @IstvánZachar that you linked seems to do all that you want and more:

Attributes[PlotExplorer] = {HoldFirst};
PlotExplorer[defPlot_] := 
  DynamicModule[{held, head, plot, range, zoomRange, defRange, 
    defSize, defEpilog, size, pt1, pt2, spt1, dist, rect = {}, 
    dragged = False, overButton = False, pushedButton = False, 
    overHor = False, overVer = False, activeHor = False, 
    activeVer = False, xPos = .5, yPos = .5, minDistance = 0.1, 
    sliderRatio = 0.05, panFactor = 10, reset, distance, slider, 
    replot, coord = None}, held = Hold@defPlot;
   head = Part[held, 1, 0];
   plot = defPlot;
   {defEpilog, defRange} = {Epilog, PlotRange} /. 
     Quiet@AbsoluteOptions@plot;
   defEpilog = defEpilog /. Epilog -> {};
   size = defSize = Rasterize[plot, "RasterSize"];
   range = zoomRange = defRange;
   Deploy@
    EventHandler[
     Dynamic[MouseAppearance[
       Show[plot, PlotRange -> Dynamic@range, 
        Epilog -> {defEpilog,(*Original epilog*)(*Replot button*)
          EventHandler[
           Inset[Graphics[{Black, 
              Dynamic@
               Opacity@If[overButton, If[pushedButton, .2, .1], 0], 
              Rectangle[{0, 0}, {1, 1}, RoundingRadius -> Offset@5], 
              Black, Dynamic@
               Opacity@If[overButton, If[pushedButton, .9, .7], 0], 
              Text["Replot", Center]}, ImageSize -> 50, 
             AspectRatio -> 1/2, 
             BaseStyle -> {FontFamily -> "Helvetica"}], Scaled@{1, 1},
             Scaled@{1, 1}], {"MouseEntered" :> (overButton = True), 
            "MouseExited" :> (overButton = False), 
            "MouseDown" :> (pushedButton = True), 
            "MouseUp" :> (pushedButton = False; 
              replot@plot)}],(*Zoom rectangle*)
          FaceForm@{Blue, Opacity@.1}, 
          EdgeForm@{Thin, Dotted, Opacity@.5}, 
          Dynamic@rect,(*Range sliders*)
          Inset[slider[Dynamic@xPos, Dynamic@overHor, 
            Dynamic@activeHor, size, True], Scaled@{.5, 0}, 
           Scaled@{.5, 0}], 
          Inset[slider[Dynamic@yPos, Dynamic@overVer, 
            Dynamic@activeVer, size, False], Scaled@{0, .5}, 
           Scaled@{0, .5}]}],(*cursor*)
       Which[dragged, "FrameRisingResize", CurrentValue@"AltKey", 
        Graphics[{Antialiasing -> False, Line@{{-1, 0}, {1, 0}}, 
          Line@{{0, -1}, {0, 1}}, 
          Dynamic@Text[
            Style[coord, FontFamily -> "Helvetica", 8], {0, 
             0}, {-1.1, -1}]}, ImageSize -> 160, ImagePadding -> 0, 
         AspectRatio -> 1, PlotRange -> {{-1, 1}, {-1, 1}}*8], 
        CurrentValue@"ControlKey" && ! overHor && ! overVer, 
        "ZoomView", CurrentValue@"ShiftKey" && ! overHor && ! overVer,
         "DragGraphics", 
        CurrentValue@"ShiftKey" && (overHor || overVer), "LinkHand", 
        True, Automatic]], 
      TrackedSymbols :> {dragged, 
        plot}], {"MouseMoved" :> (coord = MousePosition@"Graphics"), 
      "MouseClicked" :> 
       If[! overButton && CurrentValue@"MouseClickCount" == 2, 
        reset[]], 
      "MouseDown" :> 
       If[(! overHor || ! overVer), pt1 = MousePosition@"Graphics";
        spt1 = MousePosition@"GraphicsScaled"], 
      "MouseDragged" :> 
       If[(! overHor && ! overVer || dragged) && ! overButton && ! 
          pushedButton && ! activeVer && ! activeHor, dragged = True;
        Which[CurrentValue@"ControlKey", 
         dist = Last@MousePosition@"GraphicsScaled" - Last@spt1;
         range = 
          zoomRange*10^
            dist,(*"GraphicsScaled" is required below as "Graphics" \
would give jumpy results as the plot range is constantly modified.*)
         CurrentValue@"ShiftKey", 
         pt2 = MapThread[
            Rescale, {MousePosition@
              "GraphicsScaled", {{0, 1}, {0, 1}}, zoomRange}] - pt1;
         range = zoomRange - pt2, True, pt2 = MousePosition@"Graphics";
         rect = If[pt2 === None, {}, Rectangle[pt1, pt2]]]], 
      "MouseUp" :> (If[! CurrentValue@"ShiftKey" && ! 
           CurrentValue@"ControlKey" && dragged && 
          distance[pt1, pt2, zoomRange] > minDistance, rect = {};
         range = Transpose@Sort@{pt1, pt2};]; zoomRange = range;
        dragged = False)}, PassEventsDown -> True, 
     PassEventsUp -> True], 
   Initialization :> (slider[Dynamic[pos_], Dynamic[over_], 
       Dynamic[active_], size_, hor_] := 
      EventHandler[
       Dynamic[LocatorPane[
         If[hor, Dynamic[{pos, .5}, (pos = Clip[First@#, {0, 1}];

             range[[1]] = 
              If[CurrentValue@"ShiftKey", 

               First@zoomRange + (pos - .5)*
                 Abs[Subtract @@ First@zoomRange]*panFactor, 
               First@zoomRange*10^((pos - .5)*2)]) &], 
          Dynamic[{.5, pos}, (pos = Clip[Last@#, {0, 1}];

             range[[2]] = 
              If[CurrentValue@"ShiftKey", 
               Last@zoomRange + (pos - .5)*
                 Abs[Subtract @@ Last@zoomRange]*panFactor, 
               Last@zoomRange*10^((pos - .5)*2)]) &]],(*Locator below \
is required inside Graphics as LocatorPane inside Inset looses the \
crosshair image.*)
         Graphics[{Black, 
           Opacity@If[(over || active) && ! dragged, .1, 0], 
           Rectangle[{0, 0}, {1, 1}, RoundingRadius -> Offset@5], 
           Opacity@1, 
           Locator[Dynamic@If[hor, {pos, .5}, {.5, pos}], 
            Appearance -> 
             If[(over || active) && ! dragged, Automatic, None]]}, 
          ImagePadding -> 0, PlotRangePadding -> 0, 
          ImageSize -> 
           If[hor, #*{1, 0} + {0, 20} &, #*{0, 1} + {20, 0} &]@size, 
          AspectRatio -> 
           If[hor, 1/sliderRatio/First@size, sliderRatio*Last@size]], 
         Enabled -> (over || active), Appearance -> None, 
         FrameMargins -> 0, ContentPadding -> False], 
        TrackedSymbols :> {pos, over, active, 
          dragged}], {"MouseDown" :> (active = True), 
        "MouseUp" :> (active = False), 
        "MouseEntered" :> (over = ! 
            If[hor, activeVer, 
             activeHor]),(*The value of `active` must be public so \
that one slider can check whether the other is dragged,
        not to pop up if the other locator is moved over this \
slider's area.*)"MouseExited" :> (over = False)}, 
       PassEventsDown -> True];
     replot[p_] := 
      Module[{temp}, 
       Switch[head, Plot, 
        temp = ReplacePart[
          held, {{1, 2} -> {held[[1, 2, 1]], range[[1, 1]], 
             range[[1, 2]]}}];
        (*Replace plot range or insert if nonexistent*)
        plot = ReleaseHold@
          If[MemberQ[temp, PlotRange, Infinity], 
           temp /. {_[PlotRange, _] -> (PlotRange -> range)}, 
           Insert[temp, PlotRange -> range, {1, -1}]], 
        DensityPlot | ContourPlot | RegionPlot | StreamPlot | 
         StreamDensityPlot | VectorPlot | VectorDensityPlot | 
         LineIntegralConvolutionPlot, 
        temp = ReplacePart[
          held, {{1, 2} -> {held[[1, 2, 1]], range[[1, 1]], 
             range[[1, 2]]}, {1, 3} -> {held[[1, 3, 1]], 
             range[[2, 1]], range[[2, 2]]}}];
        plot = 
         ReleaseHold@
          If[MemberQ[temp, PlotRange, Infinity], 
           temp /. {_[PlotRange, _] -> (PlotRange -> range)}, 
           Insert[temp, PlotRange -> range, {1, -1}]];, _, Null]];
     reset[] := (range = zoomRange = defRange; xPos = yPos = .5);
     (*Quiet suppresses error message when Rescale[y,{x,
     x}] where y\[NotEqual]x.EuclideanDistance then defaults to \
Infinity which is fine.*)
     distance[p1_, p2_, {r1_, r2_}] := 
      Quiet[N@EuclideanDistance[Rescale[p1, r1], Rescale[p2, r2]]];)];

Here is how you can run it on your plot:

dist1 /: PDF[dist1[a_, b_], x_] := Exp[b Cos[x - a]]/(2 \[Pi] BesselI[0, b])

PlotExplorer[Plot[PDF[dist1[0, 5], x], {x, -\[Pi] + 0, \[Pi] + 0}]]

How to use a certain piece of code and call a function

You don't need to learn all the intricacies of Mathematica all at once to use it, but you'll be confused and frustrated by many of the exact things that make Mathematica such an excellent tool if you don't spend a little time getting the basics down:

$\endgroup$
  • $\begingroup$ Would this thread then rather be a duplicate of the linked one? $\endgroup$ – Yves Klett Sep 16 '15 at 9:42
  • $\begingroup$ @YvesKlett Yes, that is my opinion. $\endgroup$ – dionys Sep 16 '15 at 9:48
  • $\begingroup$ @dionys I did what you said and flagged it as duplicate of that question after changing the title $\endgroup$ – Sepideh Abadpour Sep 16 '15 at 9:59

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