0

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}]
Sepideh Abadpour
  • 967
  • 1
  • 9
  • 18
  • 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. – Sjoerd C. de Vries Sep 15 '15 at 21:26
  • 5
    @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 – Sepideh Abadpour Sep 15 '15 at 21:45
  • @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 – Sepideh Abadpour Sep 15 '15 at 21:51
  • I use that ready functions in my code? – Sepideh Abadpour Sep 15 '15 at 21:52
  • 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. – Sjoerd C. de Vries Sep 15 '15 at 21:59
  • @SjoerdC.deVries should add the implementation of the function to the top of my note book or somewhere else? – Sepideh Abadpour Sep 15 '15 at 22:19
  • That doesn't really matter as long as you run that definition before you start using the function. – Sjoerd C. de Vries Sep 15 '15 at 22:22
  • @dionys I should flag the question and request moderators to mark it as duplicate? – Sepideh Abadpour Sep 16 '15 at 09:51
  • @dionys I think I have also chosen the wrong title. My question was actually how to use that ready piece of code in my work as you see in the comments? maybe it's better to change the title to how to use a ready function in your code for panning and zooming on 2D plots? – Sepideh Abadpour Sep 16 '15 at 09:55
  • @sepideh It's up to you, but if I were you I would probably just edit out anything that isn't relevant for future readers and flag it as a duplicate question. You get some credit for helpful flags as well (in the form of meaningless internet points). – dionys Sep 16 '15 at 09:58

2 Answers2

2
Manipulate[
 Pane[
  Plot[Sin[x], {x, -10, 10}],
  ImageSize -> {300, 200},
  Scrollbars -> True,
  ScrollPosition -> {a, b}],
 {a, 10, 200},
 {b, 10, 200}]
David G. Stork
  • 41,180
  • 3
  • 34
  • 96
  • 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}] – JimB Sep 16 '15 at 13:38
1

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, sliderRatioLast@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:

dionys
  • 4,321
  • 1
  • 19
  • 46