I am trying to present Graphics
primitives dynamically. I want the displayed image to be able to update after the user changes the controls. An example would be something like
With[{triangle = {{0.13, 0.94}, {0.741, 0.744}, {0.77, 0.2}},
DynamicModule[{ctrlx, ctrly, x, y, cond, epi, lab, gra},
ctrlx=Row[{Framed[Control[{{x, 0.6, "x"}, 0, 1, 0.0001}], FrameStyle -> Thin], Spacer[10]}];
ctrly=Row[{Framed[Control[{{y, 0.6, "y"}, 0, 1, 0.0001}], FrameStyle -> Thin], Spacer[10]}];
cond=And[0.13<=x<0.9,0.2<=y<=0.567];
lab = If[
cond,
Style[Row[#], Red, FontSize -> 14] & /@ {{"x=", x}, {"y=", y}},
Style[Row[#], Black, FontSize -> 14] & /@ {{"x=", x}, {"y=", y}}
];
gra = Graphics[
{Opacity[0.1], FaceForm[Orange], EdgeForm[Purple], Polygon[rect]},
Frame -> True,
FrameLabel -> {
{Null, Dynamic@lab[[1]]},
{Null, Dynamic@lab[[2]]}
},
RotateLabel -> False,
Epilog -> Dynamic@If[cond,
{Red, Point[{x, y}]},
{Black, Point[{x, y}]}
],
PlotRange -> {{0., 1.}, {0., 1.}},
ImagePadding -> {{5, 70}, {5, 20}},
ImageSize -> Medium
];
Grid[{{gra}, {Column[{ctrlx, ctrly}]}}]
]
]
In this example, the controls change the $x$ and $y$ coordinates of a moving point.
Once the coordinates of that point enter a per-configured area (see cond
at the code snippet above) the FrameLabel
's change color and so does the point itself (from Black
to Red
, see the following two images).
Now, the question is motivated by the results of the following changes in the code:
If I attempt to bundle together all the pieces of code that need to get reevaluated every time the controls change, namely when I modify the first If
statement to read like this
{epi, {lblx, lbly}} = If[
cond,
{
{Red, Point[{x, y}]},
Style[Row[#], Red, FontSize -> 14] & /@ {{"x=", x}, {"y=", y}}
},
{
{Black, Point[{x, y}]},
Style[Row[#], Black, FontSize -> 14] & /@ {{"x=", x}, {"y=", y}}
}
];
and after I perform the needed adjustments in the body of the Graphics
ie after I adjust the following
FrameLabel -> {
{Null, Dynamic@lblx},
{Null, Dynamic@lbly}
}
and
Epilog -> Dynamic@epi
the front end cannot evaluate it. It spits an error Set::shape
with a text of
Lists {epi\$1935,{lblx\$1935,lbly\$1935}} and If[0.13<=x\$1935<0.9&&0.2<=y\$1935<=0.567,{{Red,Point[{x\$1935,y\$1935}]},(Style[Row[#1],Red,FontSize->14]&)/@{{x=,x\$1935},{y=,y\$1935}}},{{Black,Point[{x\$1935,y$1935}]},(Style[Row[#1],Black,FontSize->14]&)/@{{x=,x\$1935},{y=,y\$1935}}}] are not the same shape.
Apparently, what the front ends informs the user is that the assignment in
{epi, {lblx, lbly}} = If[...]
does not work. I assume that happens because cond
contains x
and y
which are in turn dynamically changing but I don't actually know why that is the case since in the former version of the code cond
was similarly depended upon x
and y
and If
evaluated just fine.
So the question is, how to make bundling together all the pieces of code that change when the controls change, work?
PS
I include the code that reproduces the error message for convenience
With[{rect = {{0.13, 0.2}, {0.13, 0.567}, {0.9, 0.567}, {0.9, 0.2}}},
DynamicModule[{ctrlx, ctrly, x, y, cond, epi, lblx, lbly, gra},
ctrlx = Row[{Framed[Control[{{x, 0.6, "x"}, 0, 1, 0.0001}], FrameStyle -> Thin], Spacer[10]}];
ctrly = Row[{Framed[Control[{{y, 0.6, "y"}, 0, 1, 0.0001}], FrameStyle -> Thin], Spacer[10]}];
cond = And[0.13 <= x < 0.9, 0.2 <= y <= 0.567];
{epi, {lblx, lbly}} = If[
cond,
{
{Red, Point[{x, y}]},
Style[Row[#], Red, FontSize -> 14] & /@ {{"x=", x}, {"y=", y}}
},
{
{Black, Point[{x, y}]},
Style[Row[#], Black, FontSize -> 14] & /@ {{"x=", x}, {"y=", y}}
}
];
gra = Graphics[
{Opacity[0.1], FaceForm[Orange], EdgeForm[Purple], Polygon[rect]},
Frame -> True,
FrameLabel -> {
{Null, Dynamic@lblx},
{Null, Dynamic@lbly}
},
RotateLabel -> False,
Epilog -> Dynamic@epi,
PlotRange -> {{0., 1.}, {0., 1.}},
ImagePadding -> {{20, 70}, {20, 20}},
ImageSize -> Medium
];
Grid[{{gra}, {Column[{ctrlx, ctrly}]}}],
Deployed -> True
]
]
{epi, {lblx, lbly}} =If[...]
; the rest of the code is minimally necessary in order for anyone to get a meaningfully reproducible example running; my main problem is that I need to displayGraphics
dynamically and that doesn't work when I group together all the things that need to change; I guess I could strip some more lines off but that would probably make the presentation more distant from what I think is useful; I am open to suggestions $\endgroup$