21
$\begingroup$

As shown in DynamicLocation usage, we can use it to quickly create very nice functionality, that it to refer to graphics' primitives relative coordinates without calculations of boundary etc.

enter image description here

As shown in the answer for that topic, except of DynamicLocation many related things appear:

DynamicNamespace, "DynamicName", TagBox cell expressions.

What is a big picture and how to use it properly?

$\endgroup$
18
$\begingroup$

# post under construction but feel free to add anything

# undocumented feature

# based on observation so it may be wrong

TODO:

This post does not cover few things yet, among others:

  • how to convert DynamicLocation to absolute numeric coordinates. You can use menu item Evalaution / Convert Dynamic To Literal on a generated GraphicsBox and it will do that, but this packet works only with seleciton, not with expressions/cell expressions. Would be really useful to know this. And it shpuld be possible because Graphs plots usually don't contain DynamicLocation but explicit coordinates.

  • does DynamicLocation work with Offset somehow?

TL;DR;

  • The big picture seems to be a framework for marking boxes with IDs which later can be used to find/replace/modify them (boxes).

    See: How to set focus of a dialog window? for an example with FrontEnd`BoxReferenceFind

  • In Graph/Graphics world additional tools are available so that marked graphics primitives (Disk etc) location can be expressed symbolically, without knowing its numeric values.

    See example from the OP gif:

    LocatorPane[ Dynamic @ x, Graphics[{
      EdgeForm@Thick, FaceForm@None, DynamicName[Rectangle[], "box"]
    , Arrow[{Dynamic[x], DynamicLocation["box", Automatic]}
    ]}]]
    

Symbols guide

  • DynamicName

    DynamicName[obj_, id_String, type___] typesets to

    TagBox[objBoxes, type <> "DynamicName",  BoxID->id]
    

    type can be "Private", "Public" or can be skipped but this additional argument is not supported inside Graphics.

    DynamicName is a handy way to create "marked boxes" to which we can refer later. This way we can write top level code instead of working with cell expressions.

    Additionaly, usage of TagBox makes it fully capable of a round trip to and from boxes:

    ToBoxes @ DynamicName["A", "test"]
    InputForm @ MakeExpression @ %
    
    TagBox["\"A\"", "DynamicName", BoxID -> "test"]
    
    HoldComplete[DynamicName["A", "test"]]
    

    DynamicName is preferred over explicit e.g. Rectangle[BoxID -> "id"] because of that roundtrip ability and because some primitives will not accept options. E.g. CircleBox will complain as there are no CircleBoxOptions in general, as opposed to RectangleBoxOptions RoundingRadius etc.

  • DynamicNamespace

    DynamicNamespace[name_String, expr_, options___] typesets to NamespaceBox[name, exprBoxes, opts]

    Name is optional. Don't know if that argument allows anything fancy yet.

    DynamicNamespace helps with modular coding and resolving conflicts for the same DynamicNames. E.g. Withouth the NamespaceBox only the first appearance of a specific BoxID will be known. See example 1.

  • DynamicLocation

    DynamicLocation[name_String, spec1_, spec2_] can be used in graphics primitives as a replacement for point coordinates but pointing to a primitive marked by BoxID -> name.

    • spec1 can be None or Automatic. None will point to the center of the marked primitive.

      Its behavior depends in what primitives we use it, e.g. Automatic for spec1 for line-like (Line,Arrow, etc) will point to the closest point on the edge of marked primitive with respect to parent location. See example 2.

    • spec2 is ignored when spec1 is None but otherwise can take alignment like specification, {Left, Top} etc or Scaled[t].

      Scaled[t] can parametrize position on a marked primitive's edge. Can be used for polygon/line-like primitives. See example 3.

Examples

  1. DynamicNamespace usage:

    Compare

    disk[pos_] := {
        DynamicName[Disk[pos], "name"]
      , Arrow[{pos + {2, 2}, DynamicLocation["name", Automatic]}]
    }
        (*compare this *)
    
    Graphics[ { disk[{0, 0}], disk[{0, -2}], disk[{3, 0}] }, PlotRange -> 5 ]
    
        (* with this *)
    
    Graphics[ 
       DynamicNamespace /@ { disk[{0, 0}], disk[{0, -2}], disk[{3, 0}] }
     , PlotRange -> 5 
    ]
    

    enter image description here

    In the first example all DynamicLocation["name", Automatic] point to the same, first found, BoxID -> "name". If we combine graphics from different source we can't predict names and DynamicNamespace localizes them for us preventing conflics.

  2. Context sensitive DynamicLocation:

    LocatorPane[Dynamic@x, 
     Graphics[{EdgeForm@Thick, FaceForm@None, 
       DynamicName[Rectangle[], "box"], 
       Arrow[{Dynamic[x], DynamicLocation["box", Automatic]}]
       ,
       Circle[DynamicLocation["box", Automatic]]
       }, PlotRange -> 2]]
    

    As we can see DynamicLocation["box", Automatic] means something different for Circle and for Arrow.

  3. Edge parametrization with the third argument of DynamicLocation:

    DynamicModule[{t = 0}, Column[{
      Slider@Dynamic@t, 
      Graphics[{
        EdgeForm@Thick, FaceForm@None, DynamicName[Arrow@CirclePoints[7], "box"]
      , Thick, Arrow[{{0, 0}, DynamicLocation["box", Automatic, Scaled@Dynamic@t] }]
      }, PlotRange -> 2]
    }]]
    

    enter image description here

  4. Usability in Graphics3D

    It looks like it is purely 2D feature but it works in Graphics3D Epilog, which is 2D, together with 3D primitives!

    Graphics3D[
        { DynamicName[Cuboid[{-2, -2, 0}], "box"]
        , DynamicName[Cuboid[{1, 1, -2}], "box2"]
        }
      , Epilog -> Dynamic @ {
            Arrow[{Scaled[{0, 0}], DynamicLocation["box", Automatic]}]
          , Arrow[{DynamicLocation["box", Automatic],           DynamicLocation["box2", Automatic] }]
        }
      , PlotRange -> 2
    ]
    

    enter image description here

$\endgroup$
  • $\begingroup$ Crazy exploration.. $\endgroup$ – yode Sep 7 '17 at 13:26
  • $\begingroup$ @yode It seems to be around for a long time, would really appreciate such things semi documented in experimental notebooks or something. This is really useful stuff. $\endgroup$ – Kuba Sep 7 '17 at 13:28
  • $\begingroup$ It is first function GeneralUtilities`HasDefinitionsQ return false but work well as I know.Could you tell me which is your experimental notebooks? Actually I have used AstroGrep, but I cannot find anything.. $\endgroup$ – yode Sep 7 '17 at 13:32
  • $\begingroup$ @yode I just meant 'unofficial documentation' of features that are being used but are not production ready, or something. So that users can learn more but couldn't complain if it breaks ;) $\endgroup$ – Kuba Sep 7 '17 at 13:34
  • $\begingroup$ @Kuba also see PacletFind["WolframAlphaClient"][[1]]["Location"] and CurrentValue[$FrontEnd, {StyleDefinitions, "WolframAlphaShortInput", NamespaceBoxOptions}]. The latter defines the ops it can take (as the type-set form of DynamicNamespace is NamespaceBox). The former uses it with a named string arg, etc. They also show how you make that named DynamicNamespace do special things (by changing the Format of NamespaceBox, essentially). $\endgroup$ – b3m2a1 Sep 7 '17 at 15:19
7
$\begingroup$

I think this is a very useful share for how to use this new feature,such make a smart arrow connect the explanation text with the object,for example

Graphics[{DynamicName[Disk[], "disk"], 
  DynamicName[Style[Text["This is a black disk", {3, 2}], 18, Red],"Explanation"], 
  DynamicName[Style[Text["This is a black disk", {0, 2}], 18, Blue],"AnotherExplanation"], 
  Arrow[{DynamicLocation["Explanation", Automatic],DynamicLocation["disk", Automatic]}], 
Arrow[{DynamicLocation["AnotherExplanation",Automatic],DynamicLocation["disk", Automatic]}]}]

You don't need to specify the specific coordinate for your Arrow.I think it is useful..

$\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.