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:
Image
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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

Scope (10) 

Label content (2) 

Use the underbrace with no label:

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

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]=
Image

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]=
Image

The offset is taken in the direction of the cusp:

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

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

RotateLabel (3) 

The label is by default parallel to the brace:

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

Disable rotation:

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

The angle can also be given explicitly:

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

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image
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]=
Image

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]=
Image

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]=
Image

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]=
Image
In[47]:=
List @@ %
Out[47]=
Image

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]=
Image

Position the label further from the cusp:

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

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]=
Image

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]=
Image

For an overbrace, the label is upside down:

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

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]=
Image

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]=
Image

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]=
Image

Publisher

Jaroslav Kysela

Version History

  • 1.0.0 – 26 May 2021

Related Resources

License Information