# Moving a locator based on the movement of another

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.

## 2 Answers

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] 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.

• +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++]). – C. E. Aug 13 '13 at 13:41
• @Anon Indeed, I saw this too with Print. Do you know why it is so? – Kuba Aug 13 '13 at 13:45
• 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". – C. E. Aug 13 '13 at 13:47
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}
]

• 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. – Jacob Akkerboom Aug 15 '13 at 21:22