2
$\begingroup$

I'm writing a little function to quickly draw some bezier-curves and lines on diagrams. The function opens a DialogInput. The user can use Locators to draw a line onto the diagram. When the user presses "Add curve", the graphics primitive of the drawn line is appended to the "primitives"-list. The user can add as many curves as they like. The function can either return the graphics primitives or the control points.

As the user adds more lines onto the diagram, I want all added lines to appear on the screen, but I couldn't make it work. Currently, the screen only shows the line that is currently being edited.

In the code, you can see that the Dynamic[]-function doesn't work with the graphics primitives. I tried multiple different approaches. The AppendTo[]-function also doesn't like to append anything to a dynamic expression. So at the time, I am out of ideas to make it work.

Options[curveLocator] = {
   "Background" -> 
    Graphics[{}, PlotRange -> {{-1, 1}, {-1, 1}}, Frame -> True],
   "Locators" -> 4
   };


curveLocator[OptionsPattern[]] := 
 DialogInput[
  DynamicModule[{n, points, allPoints, primitives, function}, (
    function = BezierCurve;
    n = OptionValue["Locators"];
    points = Table[{0, 0}, {i, 1, n}];
    primitives = {};
    allPoints = {};
    
    Column[Flatten@{
       (*Graphics*)
       Show[Flatten@{
          OptionValue["Background"],
          Graphics[Flatten@{
             Locator[Dynamic[points[[#]]]] & /@ Range[n],
             
             (*This works perfectly*)
             
             Dynamic[function@points],
             
             (*This doesn't work*)
             Thin, 
             Dynamic[primitives]
             }]
          },
        ImageSize -> Medium
        ],
       
       (*Controls*)
       Text[Style["Control points", Bold, 16]],
       Row[{Text["Punkte " <> ": "], 
         InputField[Dynamic[points], FieldSize -> {20, 5}]}],
       Text[Style["Grafikdirektive", Bold, 16]],
       Row[{
         PopupMenu[Dynamic[function],
          {BezierCurve, Line, Point}
          ],
         InputField[Dynamic[function]]
         }],
       Row[{
         Button["Add curve", (
           AppendTo[primitives, Dynamic[function@points]];
           AppendTo[allPoints, Dynamic[points]];
           )],
         
         Dynamic[
          Text["Added curves: " <> ToString@Length@primitives]]
         }],
       Row[{
         
         Button["Return curves as graphics primitives", 
          DialogReturn@primitives],
         Button["Return curves as points", DialogReturn@allPoints]
         }]
       }]
    )]
  ]

If you have any advice for me, please let me know.

Thanks, Fabian

$\endgroup$

1 Answer 1

5
$\begingroup$

When you do your AppendTo commands, you want to append the current value of function@points and points. You are appending a Dynamic expression, and when that gets returned, you have a Dynamic expression in your main notebook. That dynamic expression references the local variables in the DynamicModule. To see this, evaluate

curveLocator[]//FullForm

Once you dismiss the dialog, you'll see the full form, which should show you the Dynamic.

I think this is an easy fix: just remove the Dynamic from your AppendTo expressions. For clarity, I'll illustrate with an approximation of your system that minimizes all of the irrelevant details:

CaptureGraphics[g_] := graphics = g;(* convenience function for capturing the results *)
DynamicModule[
  {currentPoints = {{-1, -1}, {1, 1}}, graphics = {}, func},
  Column[
    {PopupMenu[Dynamic[func], {BezierCurve, Line, Point}],
     LocatorPane[
       Dynamic[currentPoints], 
       Dynamic[Framed@Graphics[{func[currentPoints]}, PlotRange -> 10]], 
       LocatorAutoCreate -> True],
  Button[
     "Append graphics", 
     AppendTo[graphics, func[currentPoints]];currentPoints = {{-1, -1}, {1, 1}}],
  Button["Capture all graphics", CaptureGraphics[graphics]]}]]

Using a global variable this way isn't great, but this is just for illustration. Notice that there is no Dynamic when I do the AppendTo.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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