Function Repository Resource:

GraphicsBrace

Source Notebook

Create a graphical brace object

Contributed by: Jaroslav Kysela

ResourceFunction["GraphicsBrace"][label,leftpt,rightpt]

creates a brace graphical object annotated by label that stretches from point leftpt to point rightpt.

ResourceFunction["GraphicsBrace"][label,leftpt,rightpt,vertlen]

creates the brace with edge lines of length vertlen.

ResourceFunction["GraphicsBrace"][{label,offset},leftpt,rightpt,vertlen]

creates the brace with the label offset by the distance offset from the brace cusp.

ResourceFunction["GraphicsBrace"][{label,offset,relpos},leftpt,rightpt,vertlen]

creates the brace with the label and cusp displaced by distance relpos from the left edge.

ResourceFunction["GraphicsBrace"][{label,{offset,textoffset},relpos},leftpt,rightpt,vertlen]

creates the brace with the textual label using additional offset textoffset.

Details and Options

ResourceFunction["GraphicsBrace"] can be used in Graphics. The brace object can be used to annotate different parts of a graphical scene.
The following figure depicts the meaning of some of the most important arguments and options:
The label offset scales with the size of Graphics to preserve the relative position of the label and the brace.
The anchor points can be specified either as Point objects or as {x,y} coordinate pairs.
When the first argument is set to Nothing, None or Missing[], no label is produced.
The following options can be given:
RotateLabelTruewhether to rotate the label; if so, how much
RoundingRadius0.02rounding radius of the joints of the brace curve
DirectionAutomaticdirection in which the edges extend from the anchor points
The option RotateLabel can be set to the following values:
True | Falsewhether to rotate the label or not
αrotate the label through a fixed angle
{False,α}rotate the label through a fixed angle
{True,α}add a fixed angle to the automatically calculated rotation
The option RoundingRadius can be set to the following values:
rset the radius of the joints
{rout,rin}set the radius of the outer joints and the inner joints, i.e. the cusp, independently
The option Direction can be set to the following values:
Automaticadjust the direction according to the anchor points
αdirection given by an angle
{x,y}direction given by a vector

Examples

Basic Examples (7) 

Annotate a graphical object with an underbrace:

In[1]:=
Graphics[{{Rectangle[{0, 0}, {1, .5}], ResourceFunction["GraphicsBrace"]["width", {0, 0}, {1, 0}]}}]
Out[1]=

Use multiple annotations:

In[2]:=
obj = {Gray, Rectangle[{0, 0}, {1, .4}]};
Graphics[{{obj, ResourceFunction["GraphicsBrace"][
    Style["width", 20], {0, 0}, {1, 0}], ResourceFunction["GraphicsBrace"][
    Style["height", 20], {1, 0}, {1, .4}]}}]
Out[3]=

By swapping the order of the two anchor points, create an overbrace:

In[4]:=
obj = {RGBColor[0.5, 0.8, 0.12], Rectangle[{0, 0}, {1, .5}]};
Graphics[{{obj, ResourceFunction["GraphicsBrace"]["Underbrace", {0, 0}, {1, 0}], ResourceFunction["GraphicsBrace"]["Overbrace", {1, .5}, {0, .5}, RotateLabel -> False]}}]
Out[5]=

Adjust the position and rotation of the label:

In[6]:=
obj = {Orange, Rectangle[{0, 0}, {1, .4}]};
Graphics[{obj, ResourceFunction[
   "GraphicsBrace"][{Style["width", 20], 0.1, 0.3}, {0, 0}, {1, 0}], ResourceFunction[
   "GraphicsBrace"][{Style["height", 20], 0.3, 0.8}, {1, 0}, {1, .4}, RotateLabel -> False]}]
Out[7]=

By default, the brace automatically adjusts its rotation to the annotated object:

In[8]:=
obj = {Green, EdgeForm[Thick], Rotate[Rectangle[{0, 0}, {1, .5}], 45 Degree, {0, 0}]};
Graphics[{obj, ResourceFunction[
   "GraphicsBrace"][{Style["width", 20]}, {0, 0}, {1/Sqrt[2], 1/Sqrt[
    2]}], ResourceFunction[
   "GraphicsBrace"][{Style["height", 20], 0.1, 0.8}, {1/Sqrt[2], 1/
    Sqrt[2]}, {1/(2 Sqrt[2]), 3/(2 Sqrt[2])}, RotateLabel -> True]}]
Out[9]=

Style the labels as well as the curves:

In[10]:=
obj = {Green, EdgeForm[Thick], Rectangle[{0, 0}, {1, 1}]};
Graphics[{obj,
  {Thickness[0.01], ResourceFunction[
    "GraphicsBrace"][{Style["width", 20, Red]}, {0, 0}, {1, 0}]},
  {Dashed, ResourceFunction[
    "GraphicsBrace"][{Style["height", 20, Bold], 0.1, 0.8}, {1, 0}, {1, 1}]}
  }]
Out[11]=

Use Point objects directly as anchor points:

In[12]:=
pt1 = Point[{0, 0.2}];
pt2 = Point[{0.8, 0.4}];
Graphics[{PointSize[0.02], pt1, pt2, ResourceFunction["GraphicsBrace"][Style["Point and Point", 20], pt1,
    pt2]}]
Out[14]=

Scope (10) 

Label content (2) 

Use the underbrace with no label:

In[15]:=
Graphics[ResourceFunction["GraphicsBrace"][Nothing, {0, 1}, {1, 1}]]
Out[15]=

The label does not have to be text:

In[16]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/b29fa0ef-a1d4-432f-b36e-e22e11e02cb2"]
Out[16]=

Label position (3) 

Position the label further from the cusp:

In[17]:=
lab = {Red, Disk[{0, 0}, .1]};
Graphics[ResourceFunction["GraphicsBrace"][{lab, .5}, {0, 0}, {1, 0}]]
Out[18]=

The offset is taken in the direction of the cusp:

In[19]:=
Graphics[ResourceFunction["GraphicsBrace"][{lab, .5}, {0, 0}, {1, 1}]]
Out[19]=

The textual label can be offset in the horizontal and vertical directions using an additional argument:

In[20]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/8c3be9a3-bd68-43f4-ab1b-d669cc863201"]
Out[20]=

Any specification that is valid for the third argument of Text is also allowed. Here, an Offset is used:

In[21]:=
Graphics[{
  ResourceFunction[
   "GraphicsBrace"][{"Vertically offset label", {0., Offset[{0, -20}]}, .5}, {1.5, 0}, {2.5, 1}, RotateLabel -> False],
  ResourceFunction[
   "GraphicsBrace"][{"Horizontally offset label", {0., Offset[{-150, 0}]}, .5}, {3, 0}, {4, 1}, RotateLabel -> False]
  }, ImageSize -> Large]
Out[21]=

Specify the relative position of the label with respect to the edges:

In[22]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/82b17bb6-eb61-42fc-93e9-afd7e9c55de1"]
Out[22]=

Curve dimensions (2) 

Make the edges longer:

In[23]:=
Graphics[{
  ResourceFunction["GraphicsBrace"]["No curve offset", {0, 0}, {1, 0},
    0],
  ResourceFunction["GraphicsBrace"][
   "Curve offset equal to 1", {1.5, 0}, {2.5, 0}, 1],
  ResourceFunction["GraphicsBrace"][
   "Curve offset equal to 2", {3, 0}, {4, 0}, 2]
  }]
Out[23]=

Specify the relative position of the cusp with respect to the edges:

In[24]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/ce1a3e8b-084c-4711-aed7-e902f8709dee"]
Out[24]=

Presentation (3) 

Choose different colors, thicknesses, etc. for the curve:

In[25]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/b2146e8c-3c9c-4054-8d19-fd71a181027e"]
Out[25]=

Choose different styles for the label:

In[26]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/1a76aef1-0069-4090-bd03-1e687e1b6165"]
Out[26]=

Style both the curve and the label:

In[27]:=
Graphics[{{Red, Dashed, Thick, ResourceFunction["GraphicsBrace"][
    Style["Label", Bold, Blue, Italic, 40, Background -> Yellow], {0, 0}, {0, .3}]}}]
Out[27]=

Options (8) 

Direction (3) 

By default, the curve stretches between the two anchor points:

In[28]:=
pt1 = {0, 0};
pt2 = {1, 1};
Graphics[{PointSize[0.05], Point[{pt1, pt2}], ResourceFunction["GraphicsBrace"] [
   "Default setting", {0, 0}, {1, 1}]}, Axes -> True]
Out[30]=

Specify explicitly the direction of the edges:

In[31]:=
Graphics[{PointSize[0.05], Point[{pt1, pt2}], ResourceFunction["GraphicsBrace"] ["Angle", {0, 0}, {1, 1}, Direction -> \[Pi]/8]}, Axes -> True]
Out[31]=

The direction can also be specified as a vector:

In[32]:=
Graphics[{PointSize[0.05], Point[{pt1, pt2}], ResourceFunction["GraphicsBrace"] ["Vector", {0, 0}, {1, 1}, Direction -> {2.5, 1}]}, Axes -> True]
Out[32]=

RotateLabel (3) 

The label is by default parallel to the brace:

In[33]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   "Default setting", {0, 0}, {1, 1}]}]
Out[33]=

Disable rotation:

In[34]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   "No rotation", {0, 0}, {1, 1}, RotateLabel -> False]}]
Out[34]=

The angle can also be given explicitly:

In[35]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   "Fixed angle", {0, 0}, {1, 1}, RotateLabel -> \[Pi]/2]}]
Out[35]=

The combination of both approaches yields an automatically rotated label with the explicitly given rotation offset:

In[36]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   "Fixed angle offset", {0, 0}, {1, 1}, RotateLabel -> {True, -(\[Pi]/2)}]}]
Out[36]=

RoundingRadius (2) 

Adjust the radius of the joints:

In[37]:=
Graphics[{
  ResourceFunction["GraphicsBrace"] ["Default radius", {0, 1}, {1, 1}],
  ResourceFunction["GraphicsBrace"] [
   "Larger radius", {0, 0.5}, {1, 0.5}, RoundingRadius -> 0.1],
  ResourceFunction["GraphicsBrace"] ["Smaller radius", {0, 0}, {1, 0},
    RoundingRadius -> 0.005]
  }]
Out[37]=

The radius of the cusp and outer joints can be specified independently:

In[38]:=
Graphics[ResourceFunction["GraphicsBrace"] [
  "Outer radius = 0.15, inner radius = 0.05", {0, 1}, {1, 1}, RoundingRadius -> {0.15, 0.05}]]
Out[38]=

Applications (2) 

Make a technical drawing with proper physical units:

In[39]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/adfc45ce-cdb9-4b2e-9de4-0d80315e3e46"]
Out[39]=

Describe the regions where a given function is monotonically increasing and decreasing:

In[40]:=
f[x_] := x Exp[-x^2];
argm = ArgMax[f[x], x]
Out[41]=
In[42]:=
Plot[f[x], {x, 0, 2}, PlotRange -> {All, {0, .7}},
 Epilog -> {
   ResourceFunction[
    "GraphicsBrace"][{Style["increasing", Bold, 15], .05}, {argm, f[argm]}, {0, f[0]}, Direction -> \[Pi]/2, RotateLabel -> False],
   ResourceFunction[
    "GraphicsBrace"][{Style["decreasing", Bold, 15], .05}, {2, f[2]}, {argm, f[argm]}, Direction -> \[Pi]/2, RotateLabel -> False]
   }, ImageSize -> Large]
Out[42]=

Properties and Relations (1) 

GraphicsBrace can be used in Graphics the way that an underbrace is used in text:

In[43]:=
Graphics[{Text[Style["some text", 20], {0, 0}], ResourceFunction["GraphicsBrace"][
   Nothing, {-0.05, -0.01}, {0.05, -0.01}, 0, RoundingRadius -> 0.01]}, ImageSize -> Tiny]
Out[43]=

Possible Issues (5) 

When the first argument is to be taken as a literal, wrap it in Inset:

In[44]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   Inset[{"Some text", 0.1, 0.5}, {0, 0}], {0, 0}, {1, 0}]}]
Out[44]=

When the other arguments are not numeric, no evaluation of GraphicsBrace takes place:

In[45]:=
Clear[pt]
Graphics[{Rectangle[], ResourceFunction["GraphicsBrace"] ["Label", pt, {1, 0}]}]
Out[46]=
In[47]:=
List @@ %
Out[47]=

The label may be set too close to the cusp:

In[48]:=
lab = {Red, Disk[{0, 0}, .1]};
Graphics[ResourceFunction["GraphicsBrace"][lab, {0, 0}, {1, 0}]]
Out[49]=

Position the label further from the cusp:

In[50]:=
Graphics[ResourceFunction["GraphicsBrace"][{lab, .2}, {0, 0}, {1, 0}]]
Out[50]=

When the line segments are too small with respect to the rounding radii, undesired behavior occurs:

In[51]:=
Graphics[{ResourceFunction[
   "GraphicsBrace"] [{"Default radius", 0.01}, {0, 1}, {.03, 1}, 0]}]
Out[51]=

To prevent this, adjust the rounding radii appropriately:

In[52]:=
Graphics[{ResourceFunction[
   "GraphicsBrace"] [{"Default radius", 0.01}, {0, 1}, {.03, 1}, 0, RoundingRadius -> 0.005]}]
Out[52]=

For an overbrace, the label is upside down:

In[53]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   Style["Overbrace", 20, Bold], {1, 0}, {0, 0}]}]
Out[53]=

Turn off the automatic rotation of the label:

In[54]:=
Graphics[{ResourceFunction["GraphicsBrace"] [
   Style["Overbrace", 20, Bold], {1, 0}, {0, 0}, RotateLabel -> False]}]
Out[54]=

Neat Examples (2) 

Use the brace as a graphics primitive for artistic drawing:

In[55]:=
Graphics[{Thick, Table[With[{n = 5 s}, {ColorData[10][s], ResourceFunction["GraphicsBrace"][Nothing, ##, RoundingRadius -> .4] & @@@ Partition[N@CirclePoints[{0.3 n - 0.2, Boole@EvenQ@n}, n], 2, 1, {-1, 2}]}], {s, 3}]}, Background -> Lighter[Orange, 0.8]]
Out[55]=

Annotate the side lengths of a dynamically changing triangle:

In[56]:=
pt1i = {0.06, -0.90};
pt2i = {-0.53, -0.05};
pt3i = {0.56, 0.90};
variableBrace[lab_, pt1_, pt2_, ang_ : Automatic] := ResourceFunction["GraphicsBrace"][
  Style[ToString[Subscript["\[CapitalDelta]L", lab], TraditionalForm] <> " = " <> ToString[NumberForm[EuclideanDistance[pt1, pt2], 3]], 20], pt1, pt2, Direction -> ang, RoundingRadius -> .05]
Manipulate[Graphics[{Polygon[{pt1, pt2, pt3}],
   variableBrace[1, pt1, pt3, dir],
   variableBrace[2, pt3, pt2, dir],
   variableBrace[3, pt2, pt1, dir]
   }, PlotRange -> 1.],
 {{pt1, pt1i}, Locator}, {{pt2, pt2i}, Locator}, {{pt3, pt3i}, Locator},
 {{dir, Automatic, "Direction"}, {Automatic -> "Tangent", 0 -> "Fixed"}}]
Out[60]=

Publisher

Jaroslav Kysela

Version History

  • 1.0.0 – 26 May 2021

Related Resources

License Information