fletcher.edge()
Draw a path with arrow marks, labels, and automatic snapping to nodes.
fletcher.edge( ..args: coord str content, vertices: array, stroke: stroke, dash, extrude: number length array, corner-radius: length number none, marks, mark-scale: number percent auto, label: content dictionary array, label-pos: ratio number length, label-side: auto none center top bottom left right start end, label-sep: length, label-fill, label-angle: angle auto top bottom left right, label-anchor: anchor, snap-to: none auto pair, snap-method: "trim" "move" pair, outset: length pair, shorten: length number array, name: label str, decorate, layer: number, crossing: bool, crossing-fill: color, crossing-thickness: number length, in-math: bool, draw: function, debug, )
..args
An edge’s positional arguments may specify:
- the edge’s
vertices, each given as a CeTZ coordinate; - the CeTZ path to apply edge marks, styles, and labels to;
- the edge’s
marks, e.g.,"->"or"solid=/=solid"; - the body content of an edge
label, e.g.,$f$; or - some other style flags (
dashed,dotted,double,triple,crossing).
Vertex coordinates come first but are optional:
edge(from, to, ..) // explicit start and end
edge(to, ..) == edge(auto, to, ..) // start from previous node
edge(..) == edge(auto, auto, ..) // between previous and next nodes
edge(from, v1, v2, ..vs, to, ..) // multiple vertices
edge(from, "->", to) // for two vertices, marks can go in the middleVertices after the first one can be relative coordinate shorthand strings containing the characters or commas, e.g., edge((0,0), "u,rr,d").
If applying edge effects to a CeTZ path, no vertices should be given and the path should be the first argument:
edge(cetz.draw.bezier(..), "<->") // add marks to a cetz pathIf given as positional arguments, an edge’s marks and label are disambiguated based on their types. For example, the following are equivalent:
edge(.., $f$, "->")
edge(.., "->", $f$)
edge(.., $f$, marks: "->")
edge(.., "->", label: $f$)
edge(.., label: $f$, marks: "->")vertices
()Array of coordinates for the edge.
Vertices can also be specified as leading positional arguments (so edge((0,1), (1,1), $f$, ..) is the same as edge($f$, vertices: ((0,1), (1,1)), ..)).
stroke
autoStroke style for the edge.
The default thickness matches the thickness of the symbol in the default math font with the current text size.
The default stroke style can be set with the edge-stroke option of diagram() or with cetz.draw.set-style(edge: (stroke: ..)).
dash
autoSet the dash property of the current stroke style.
You can also set the dash style using stroke; this is simply an alias.
extrude
autoDraw a separate stroke for each extrusion offset to obtain a multi-stroke effect. Offsets may be numbers (specifying multiples of the stroke’s thickness) or lengths.
Some line styles can also be used as a shortcut:
edge("=")produces(extrude: (-2, 2))edge("==")produces(extrude: (-4, 0, 4))
corner-radius
autoRadius of curvature for rounded corners.
For extruded edges, this defines the radius of curvature of the innermost stroke as you go around the bend. Note that none, which enables miter joins, is different from 0.
This length specifies the corner radius for right-angled bends. The actual radius is smaller for acute angles and larger for obtuse angles to balance things visually. See path-effect.corner-radius for details.
marks
()Marks or arrows to draw along the edge.
TODO
mark-scale
autoMark size multiplier.
The size parameter of each mark is multiplied by the mark scale before being drawn.
This is an edge style that can also be set using diagram(mark-scale: ..) or cetz.draw.set-style(edge: (mark-scale: ..)).
label
noneContent to place along the edge.
#diagram(edge("->", $f$))The label body may also be given as a positional argument.
edge(.., [Label])
edge(.., label: [Label])Label options can be specified with a dictionary, or as named arguments by adding label- as a prefix . For example, the following are the same:
edge(.., label: (body: [Label], pos: 25%))
edge(.., [Label], label-pos: 25%)Possible label options are:
body: the content to drawangle: orientation of the label body (seelabel-angle)pos: the label’s position along the edge path (seelabel-pos)sep: padding between the label’s body and the path (seelabel-sep)side: which side of the edge to place the body (seelabel-side)anchor: the CeTZ anchor to use for label body (seelabel-anchor)
Multiple labels can be specified with an array:
edge(.., label: ([First label], (body: [Second label], pos: 25%)))label-pos
50%Position along the edge path to place labels.
This can be a ratio, relative to the total path length, or a float whose integer part refers to the segment number and whose fractional part interpolates along the segment (see Path anchors).
#diagram({
edge((0,0), (1,1), (2,1), (2,0), "->", label: (
(body: [1st], pos: 0.5),
(body: [2nd], pos: 1.5),
(body: [3rd], pos: 2.5, side: right),
))
})This can be given as an edge argument like edge(.., $f$, label-pos: 50%) or as a label option like edge(.., label: (body: $f$, pos: 50%)).
label-side
autoWhich side of the edge to place the label on.
If auto, the label is placed roughly above straight edges, or on the outside of curved edges.
An alignment (e.g., top, left, top + left) means place the label beside the edge to whichever side is nearer that direction. If given as an alignment, the side may flip depending on the edge’s angle.
If true, the label is placed above the edge assuming it goes left to right; false is the opposite side. In these cases, the side never flips depending on the edge’s angle.
If center or none, the label is placed directly over the edge, and the label fill defaults to white.
The special alignment values start and end place the label before or after a point, travelling along the edge. This works best when used like (pos: 0%, side: start) or (pos: 100%, side: end).
#diagram(edge((0,0), "->", (1,1), label: (
(body: `start`, side: start, pos: 0%),
(body: `left`, side: left, pos: 0%),
(body: `right`, side: right, pos: 0%),
(body: `center`, side: center, pos: 50%),
(body: `end`, side: end, pos: 100%),
(body: `top`, side: top, pos: 100%),
(body: `bottom`, side: bottom, pos: 100%),
)))This can be given as an edge argument like edge(.., $f$, label-side: top) or as a label option like edge(.., label: (body: $f$, side: top)).
label-sep
3ptSeparation between label body and the edge.
This can be given as an edge argument like edge(.., $f$, label-sep: 3pt) or as a label option like edge(.., label: (body: $f$, sep: 3pt)).
label-angle
0degAngle of the label’s body.
A positive angle goes anticlockwise, with 0deg being upright.
An alignment (e.g., top, right) means to rotate the label with the edge’s direction, such that the label is upright along edges going in that direction.
If auto, the best of left or right is chosen; that is, the label is rotated to be tangent to the edge and roughly the right way up.
This can be given as an edge argument like edge(.., $f$, label-angle: auto) or as a label option like edge(.., label: (body: $f$, angle: auto)).
label-anchor
autoThe CeTZ anchor to use for the label content.
If auto, the anchor is automatically chosen depending on label-side and the edge’s angle. This must be auto if the side option is set.
snap-to
(auto, auto)Names or coordinates of nodes or CeTZ objects to snap the edge’s ends to.
This can be none to disable snapping or auto to detect nearby nodes. A pair such as (none, auto) can be used to control snapping at each end independently.
You can use the "edge.snap" debug option to see the edge’s path before snapping is applied. Additionally, "edge.snap.from" and "edge.snap.to" highlight which nodes actually get snapped to.
snap-method
autoWhen an edge snaps to an object’s outline, the edge can be shifted in two ways: one method is to shorten the edge to the point where it meets the object (the "trim" method); the other method is to move the edge’s end vertex to the edge of the object (the "move" method).
You can pass a pair such as ("trim", "move") to control the methods for the start and end of the edge independently.
#diagram(
debug: "edge.snap",
node-fill: yellow,
node-shape: circle,
node((0,0), [Snapping]),
edge("->", `trim`, bend: +90deg, snap-method: "trim"),
edge("->", `move`, bend: -90deg, snap-method: "move"),
node((1,0), [Method]),
)outset
autoGap between the end of the edge and connected nodes.
Similar to node.outset, but specific to the edge instead of the target node. Can be a single length or a pair of lengths (from, to) to control the outset at either end.
#diagram(
node-fill: teal,
node((0,0), [A], <a>),
node((1,0), [B], <b>),
edge(<a>, "<->", <b>, bend: +60deg, [No outset]),
edge(<a>, "<->", <b>, bend: -60deg, outset: 5pt, [Outset]),
)See also shorten.
shorten
0Distance to shorten the edge at either end.
If a length is given, the edge is shortened at both ends. A pair of lengths (start, end) controls shortening at either end of the edge independently.
See also outset.
name
noneName of the edge for use with coordinate anchors.
Giving a name to an edge allows the use of path anchors to connect other edges or CeTZ objects.
decorate
autoApply CeTZ path decorations do the edge, such as wave or zigzag effects.
This can be a dictionary containing any of:
kind, one of"wave","zigzag","square"or"coil"wavelengthamplitudeshorten, distance from ends to start effect fromsmooth, distance over which to “ramp” the effect’s amplitude for a smoother transition
The shorten and smooth options can be lengths, distances (interpreted as multiples of wavelength) or a pair of these, controlling the values at the star and end of the path independently.
#diagram(
edge("ru,r", decorate: (kind: "wave", shorten: 5mm, smooth: 0)),
)#diagram(edge("rr", decorate: (
kind: "square",
amplitude: 3mm,
shorten: 0,
smooth: 2mm,
)))#diagram(
edge("ru,r", "~>", decorate: (shorten: (2, 0))),
)layer
autoCanvas layer to draw edge on.
Edges with equal layer are drawn in the order they are inserted.
See also node.layer, which is 1 by default.
crossing
falseDraw a backdrop under the edge to give the illusion of it crossing over other lines.
If true, draws a backdrop of color crossing-fill with a thickness crossing-thickness, which are both styles that can be set at the diagram level.
#diagram(
edge-stroke: 2pt,
edge((0,1), (1,0)),
edge((0,0), (1,1)),
edge((2,1), (3,0)),
edge((2,0), (3,1), crossing: true),
)To make sure crossing lines are drawn above other lines, order them later in the diagram or use layer.
crossing-fill
autoColor of the “crossing” backdrop (drawn when crossing is enabled). This should match the background of the figure to give the illusion of breaking lines below it.
crossing-thickness
autoWidth of the “crossing” backdrop (drawn when crossing is enabled) as a length or a multiple of the stroke’s thickness.
in-math
falseWhether to return a metadata object which can be placed inside equations, instead of returning an array of functions which can be inserted into a CeTZ canvas.
If you often use fletcher in math mode, consider defining the shortcut:
#let hom = edge.with(in-math: true)The hom edge function can be inserted into equations, like so:
#diagram($x hom(|=>) & f(x)$)See also node.in-math.
draw
autoFunction accepting an array of vertices and returning the CeTZ path.
This internal argument isn’t meant for normal use. It is set automatically depending on the inferred edge kind. For example, if bend: 30deg is given, draw defaults to cetz.draw.arc(..) with appropriate end points.
debug
autoEnable debug annotations for only this edge. See Edge debug options.
If auto, the debug setting is inherited from the enclosing diagram() or flexigrid().