3
$\begingroup$

Continuing the discussion started in the thread here, I've tried to recreate the code from scratch. I thus looked to constrain the movement of a locator to the graph defined by

f[t_] := t {Cos[10 t], Sin[10 t]}

If the locator is at point pt, then

Table[{t,Norm[f[t] - pt]}, {t, 0, 2, 0.001}]

is a list of couple {t, distances}, which can be sorted with Sort and the t-value can be found back using

First[First[Sort[Table[
{t, Norm[f[t] - pt]}
, {t, 0, 2, 0.001}], (#1[[2]] < #2[[2]]) &]]]

Changing the variable pt by # to create a Pure Function used by the second argument of the Locator command, I tried the code

Show[
 ParametricPlot[f[t], {t, 0, 2}]
 ,
 Graphics[{
   Locator[ptt,
    ptt =
     (f[First[First[Sort[Table[
            {t, Norm[f[t] - #]}
            , {t, 0, 2, 0.001}], (#1[[2]] < #2[[2]]) &]]]]) &
    ]
   }]
 ]

which doesn't work at all. I think there is an error due to expansions of some sorts, but don't know where. Any help with this? The answer found in the link above is working, of course, but I'm trying to find something "shorter", if possible.

All help, as always, very much appreciated!

$\endgroup$
3
$\begingroup$

You're missing a Dynamic around ptt and the update function. You also have a misplaced parenthesis in your update function.

ptt = {0., 0.};
f[t_] := t {Cos[10 t], Sin[10 t]}
Show[ParametricPlot[f[t], {t, 0, 2}], 
 Graphics[{Locator[
    Dynamic[ptt,
           (ptt = f[First[First[Sort[Table[{t, Norm[f[t] - #]}, {t, 0, 2, 0.001}],
                                     (#1[[2]] < #2[[2]]) &]]]]) &]
     ]}
 ]]

Update

Your approach can be sped up by storing the evaluations of f[t] instead of recalculating them each time the Locator moves:

ptt = {0., 0.};
f[t_] := t {Cos[10 t], Sin[10 t]}
fvalues = f /@ Range[0, 2, 0.001];
Show[ParametricPlot[f[t], {t, 0, 2}], 
 Graphics[{Locator[
    Dynamic[ptt, (ptt = First @ SortBy[fvalues, Function[f0, Norm[f0 - #]]]) &]
  ]}]]

Even more efficiency can be obtained by using Nearest instead of sorting, as in my answer to the linked question. You can apply Nearest to fvalues above or the values already calculated by ParametricPlot, which I get below using Cases.

ptt = {0., 0.};
f[t_] := t {Cos[10 t], Sin[10 t]}
plot = ParametricPlot[f[t], {t, 0, 2}];
ptfn = Nearest @ First @ Cases[plot, Line[p_] :> p, Infinity];
Show[plot, Graphics[{Locator[Dynamic[ptt, (ptt = First@ptfn[#]) &]]}]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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