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

-
This you look at the other related answers? Such as this: mathematica.stackexchange.com/questions/26891/… –  Pickett Aug 13 '13 at 10:36
Also related: mathematica.stackexchange.com/questions/22134/… –  Michael E2 Aug 13 '13 at 15:26

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++]). –  Pickett 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". –  Pickett 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
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.3888944983482361, "perplexity": 2304.2075866007094}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2014-35/segments/1409535919066.8/warc/CC-MAIN-20140901014519-00097-ip-10-180-136-8.ec2.internal.warc.gz"}