Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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!

share|improve this question

1 Answer 1

up vote 3 down vote accepted

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[#]) &]]}]]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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