# Creating a function takes a list and dynamically modifies that list [duplicate]

I'm trying to create a function that uses a dynamic locatorpane to populate a list with the coordinates of user defined locators (added by alt+clicking). This code works fine:

one = ExampleData[{"TestImage", "Airplane"}]

ptsa = {};
ptsb = {};

Button["Reset points", ptsa = {}]
LocatorPane[Dynamic[ptsa],
Dynamic[
Show[one,
Graphics[{
Table[(*draw arrows between locators*)
Arrow[{
ptsa[[i]], ptsa[[i + 1]]
}],
{i, 1, Floor[Length[ptsa], 2], 2}
],
Table[
Text[(i + 1)/2,
ptsa[[i]] + (ptsa[[i + 1]] - ptsa[[i]])/2 +
Cross[ptsa[[i + 1]] - ptsa[[i]]]/
EuclideanDistance[ptsa[[i + 1]],
ptsa[[i]]]*10],(*display line # 5 pixels orthogonal to line \
midpoint*)
{i, 1, Floor[Length[ptsa], 2], 2}
]
}]
]
],
LocatorAutoCreate -> True,
Appearance -> Style["\[CenterDot]", Medium, Red]]


That works for the single list: "ptsa" and allows me to insert points into "ptsa" with a point-and-click interface.

However, I need to do this for many different lists (ptsb, ptsc, ptsd, etc). I tried making a function ui[ptsa_] := LocatorPane[...] so I can just do ui[ptsb] in the future, but this simply inserts {} into ptsa, which doesn't help.

I also tried defining the above simply as a = LocatorPane[...] and trying

a /. ptsa -> ptsb


but that doesn't work either. I'm not sure how to approach this.

• Welcome to MMA.SE. Please try to provide a minimal working example for you questions in the future. The LocatorPane and other details are not relevant there. Please take a look at HoldFirst documentation's examples, I believe there is the answer to your question.
– Kuba
Apr 6 '16 at 5:37
• I'm voting to close this question as off-topic because it is to localized.
– Kuba
Apr 8 '16 at 8:02
• @Kuba. I don't agree. It's a simple question with a simple answer, but it certainly is an issue that often comes up. Apr 8 '16 at 13:57
• @m_goldberg that's probably arguable :) I think it is in OP's reach to reduce the problem to drop Locator/Graphics context, yet my comment was left without any answer. That's why I voted to close as too localized. Furthermore, after reducing the problem what stays is a simple mistake or a duplicate candidate.
– Kuba
Apr 8 '16 at 14:25

All you have to do is give ui the attribute HoldFirst. It also a good idea to make the image an argument of ui. That is, define

SetAttributes[ui, HoldFirst];
ui[pts_, img_Image] :=
LocatorPane[
Dynamic[pts],
Dynamic[
Show[
img,
Graphics[
{Table[
Arrow[{pts[[i]], pts[[i + 1]]}],
{i, 1, Floor[Length[pts], 2], 2}],
Table[
Text[
(i + 1)/2,
pts[[i]] + (pts[[i + 1]] - pts[[i]])/2 +
Cross[pts[[i + 1]] - pts[[i]]] /
EuclideanDistance[pts[[i + 1]], pts[[i]]]*10],
{i, 1, Floor[Length[pts], 2], 2}]}]]],
LocatorAutoCreate -> True,
Appearance -> Style["\[CenterDot]", Medium, Red]]


Then

ptsa = {};
ui[ptsa, one]


Dynamic @ ptsa

{{231.6, 158.5}, {213.2, 74.}, {70.8, 130.}, {156.4, 83.5}}