4
$\begingroup$

My problem is:

I want two Locators to simulate a vector in the following sense:

  • The first Locator is the base and the second the tip of the vector.

  • When I move the tip, the base does not move (hence the vector changes).

  • When I move the base, the vector is unchanged, and therefore the tip (and the Locator) moves.

How can I achieve that?

I have tried storing the previous value of the base and then test if the current value is different. And if so updated the position of the tip. I can however not make that work, when using 'Module'. I suspect that there is a more elegant solution.

$\endgroup$
2

2 Answers 2

5
$\begingroup$

This seems to be a duplicate but I can't find it :). Meanwhile, you can use second argument of Dynamic.

x = {0, 0}; y = {1, 1}; w = y - x;


Deploy@Graphics[{
                 Locator@Dynamic[x, (x = #; y = x + w;) &],
                 Locator@Dynamic[y, (y = #; w = y - x;) &],
                 Dynamic@Arrow[{x, y}]
                }
                , PlotRange -> 2]

enter image description here

In case of multiple vectors one may want to save space and make code more transparent so we can use extended version of Dynamic second argument to achieve this:

Deploy@Graphics[{
                 Locator@Dynamic[x, {(w = y - x;) &, (x = #; y = x + w) &, None}],
                 Locator@Dynamic[y],
                 Dynamic@Arrow[{x, y}]
                }
               , PlotRange -> 2]

Now we are working only with base, moreover w can be scoped to particular Locator.

There is huge advantage of the second method, well, not exactly the method but the usage of f_start and f_end. You can calculate w once, not all the time you are dragging the Locator.

$\endgroup$
3
  • $\begingroup$ +1 I like this answer a lot and a learned something from it! btw. while I researched it I noticed that the exact number of times w is calculated in the second version is twice every time you drag that locator. (Method; first n=0; and then inside the anonymous function Print[n++]). $\endgroup$
    – C. E.
    Aug 13, 2013 at 13:41
  • $\begingroup$ @Anon Indeed, I saw this too with Print. Do you know why it is so? $\endgroup$
    – Kuba
    Aug 13, 2013 at 13:45
  • $\begingroup$ No! I became very curious but I suppose there is no good answer. It's not what is says in the documentation so I guess that's just "how it is". $\endgroup$
    – C. E.
    Aug 13, 2013 at 13:47
4
$\begingroup$
p1save = {0, 0}; p2save = {1, 1};
Manipulate[
        If[p1 != p1save, p2 = p2 + p1 - p1save; p1save = p1];
        Graphics[Arrow[{p1, p2}], PlotRange -> {{-5, 5}, {-5, 5}}, AspectRatio -> 1],
 {{p1, p1save}, Locator}, {{p2, p2save}, Locator}
 ]

or a little bit more sophisticated, preventing the arrow to overflow the graphics window:

p1save = {0, 0}; p2save = {1, 1};  min = -5; max = 5;
Manipulate[
 If[Or @@ ((min > # || # > max) & /@ Flatten[{p1, p2 + p1 - p1save}]),
                                               p1 = p1save; p2 = p2save];
 If[p1 != p1save, p2 = p2 + p1 - p1save; p1save = p1; p2save = p2];
 Graphics[Arrow[{p1, p2}], PlotRange -> {{min, max}, {min, max}},  AspectRatio -> 1],
 {{p1, p1save}, Locator}, {{p2, p2save}, Locator}
 ]
$\endgroup$
1
  • $\begingroup$ Looking good. But somehow in the second example if I move the base of the arrow, the head of the arrow moves at constant speed. $\endgroup$ Aug 15, 2013 at 21:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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