Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Interactive 2d zoom and some Dynamic questions

74 views
Skip to first unread message

Szabolcs Horvát

unread,
Jan 2, 2008, 1:20:16 AM1/2/08
to

Happy new year, MathGroup!

And now, the question:

First of all, those people who haven't seen it yet should definitely
check out Daniel Huber's very nice Zoom2D palette:
http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/58c77e4614440e57/5876f0611112765e

But I would like to have something simpler, a "quick and dirty" zoom
that has the simplest possible UI, and keeps the graphic in the
notebook. So I came up with this:

zoomGraphics[graph_Graphics] :=
With[
{gr = First[graph],
opt = DeleteCases[Options[graph], PlotRange -> _],
plr = PlotRange /. Options[graph, PlotRange],
rectangle = {Dashing[Small],
Line[{#1, {First[#2], Last[#1]}, #2,
{First[#1], Last[#2]}, #1}]} & },
DynamicModule[{dragging = False, first, second, range = plr},
Panel@EventHandler[
Dynamic@Graphics[
If[dragging, {gr, rectangle[first, second]}, gr],
PlotRange -> range, Sequence @@ opt
],
{{"MouseDown", 1} :> (first = MousePosition["Graphics"]),
{"MouseDragged", 1} :>
(dragging = True;
second = MousePosition["Graphics"]),
{"MouseUp", 1} :>
If[dragging,
dragging = False;
range = Transpose@{first, second}, range = plr] }
]
]]

Usage example:

Plot[1/x, {x, 0, 1}] // zoomGraphics

Drag to zoom, click to reset. Remove Panel if you don't like it (or
replace it with Framed). It's there to show the active ("draggable") area.

I do not understand Dynamic things well, so comments, suggestions (e.g.
for improving performance), problem cases where zoomGraphics fails are
most welcome.

One of the biggest problems with this is that EvantHandler prevents
resizing the graphic from working. This is unacceptable because if we
want to zoom, most likely we also want to keep the resize functionality.

It also prevents dynamic things, like Locators from working properly. I
could set PassEventsDown -> True in EventHandler, but zooming would
still interfere with resizing or moving a Locator (and other strange
behaviour appears too.) One solution that I can imagine is to zoom only
while CTRL (or some other modifier key) is pressed. But I do not know
how to implement this properly. This is what I have so far:

zoomGraphics[graph_Graphics] :=
With[
{gr = First[graph],
opt = DeleteCases[Options[graph], PlotRange -> _],
plr = PlotRange /. Options[graph, PlotRange],
rectangle = {Dashing[Small],
Line[{#1, {First[#2], Last[#1]}, #2, {First[#1],
Last[#2]}, #1}]} &,
keyCheck =
Function[{arg}, If[CurrentValue["ControlKey"], arg], HoldAll]},
DynamicModule[{dragging = False, first, second, range = plr},
Panel@EventHandler[
Dynamic[
Graphics[
If[dragging, {gr, rectangle[first, second]}, gr],
PlotRange -> range, Sequence @@ opt
]],
{{"MouseDown", 1} :>
keyCheck[first = MousePosition["Graphics"]],
{"MouseDragged", 1} :>
keyCheck[dragging = True; second = MousePosition["Graphics"]],
{"MouseUp", 1} :>
keyCheck@
If[dragging, dragging = False;
range = Transpose@{first, second}, range = plr]}]
]]

OK, now zooming only works while CTRL is pressed. Now it is somewhat
safer to set PassEventsDown -> True, and resizing works when CTRL is not
pressed. But resizing and selecting graphics interferes with zooming
when CTRL is pressed. The zoom level is also often reset unexpectedly
if CTRL is not released (and pressed again), and the graphics are not
deselected, between consecutive zoom attempts. I don't completely
understand what is happening here. Is it possible to somehow set
PassEventsDown -> True only when CTRL is not pressed? As a desperate
attempt, I tried PassEventsDown ->
Dynamic@Not@CurrentValue["ControlKey"], but, unsurprisingly, it does not
work.

As an alternative solution, I also tried using
GraphicsGrid[{{zoomGraphics[someGraphic]}}] with the original version of
zoomGraphics to enable resizing (not moving Locators), but now the
events don't seem to reach the EventHandler.

Another question: Could someone please explain, preferably with a
working example, what PassEventsUp is for?

Szabolcs

dh

unread,
Jan 4, 2008, 5:42:10 AM1/4/08
to

Hi Szabolcs,

nice little tool. If you don't mind, I like to propose to add axes to

the zoomed picture by adding:

AxesOrigin -> {Min[range[[1]]], Min[range[[2]]]}

to your graphics.

happy New Year, Daniel

m...@inbox.ru

unread,
Jan 6, 2008, 5:51:15 AM1/6/08
to
On Jan 2, 12:20 am, Szabolcs Horv=E1t <szhor...@gmail.com> wrote:
> Happy new year, MathGroup!
>
> And now, the question:
>
> First of all, those people who haven't seen it yet should definitely
> check out Daniel Huber's very nice Zoom2D palette:http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_...

You can dynamically change Deployed:

DynamicModule[{mp, pos = {.5, .5}, sz = {1, 1}, mpos, f = True},
mp[] := MousePosition["GraphicsScaled"];
EventHandler[
Style[Graphics[
Inset[GraphData["HundredTwentyCellGraph"],
Center, Dynamic@Scaled@pos, Dynamic@Scaled@sz],
ImageSize -> 500], Deployed -> Dynamic[f]],
{"MouseDown" :>
(If[f && CurrentValue["MouseButtonTest"] &&
CurrentValue["MouseClickCount"] == 2,
pos = {.5, .5}; sz = {1, 1},
If[f && CurrentValue["ControlKey"],
f = False,
If[! f && CurrentValue["AltKey"],
f = True]]];
mpos = mp[]),
"MouseDragged" :>
(If[f,
If[CurrentValue["MouseButtonTest"],
pos -= 2/sz[[1]] (mp[] - mpos),
sz += 4 sz[[1]] (mp[][[2]] - mpos[[2]])];
mpos = mp[]])},
PassEventsDown -> True]]

Here dragging the mouse with the left button pressed pans the graphic,
dragging the mouse up/down with the right button pressed zooms in/out,
left double click resets to defaults, but if you do Control-click, you
switch to the standard interactive editing mode. Alt-click switches
back to zoom mode.

Maxim Rytin
m...@inbox.ru

Jerry

unread,
Jan 7, 2008, 2:49:13 AM1/7/08
to
Hi, did you mean to replace the DynamicModule section of
the above code with yours? I tried that and it seems to work
like you say but the thing plotted isn't a 2D plot of 1/x vs
x, it's a circular collections of connected dots, a "graph"
I'd guess. Seems like I'm doing something wrong.
0 new messages