# Curved arrow using Makie.jl

**URL:** <https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013>\
**Category:** Visualization\
**Tags:** makie, cairomakie\
**Created:** [July 13, 2024, 6:52pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013 "2024-07-13T18:52:46Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![albertomercurio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albertomercurio/32/27051_2.png) [@albertomercurio](https://discourse.julialang.org/u/albertomercurio)\
**Post date:** [July 13, 2024, 6:52pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/1 "2024-07-13T18:52:46Z")

</div>

Hello,

I would like to draw a curved arrow inside an axis using Makie.jl

More precisely, I have a starting point `x0`, a final point `x1`, and I want to draw and arrow which is not straight, but curved in some way.

How can I do it? The `arrows` function seems to support only straight arrows.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [July 13, 2024, 7:07pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/2 "2024-07-13T19:07:26Z")

</div>

If you dont find a solution with Makie.jl alone, check BezierCurve in Meshes.jl. you can visualize them as described in the docs.

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [July 13, 2024, 7:20pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/3 "2024-07-13T19:20:12Z")

</div>

Makie does have a `BezierPath` function that you can give Bezier commands in the syntax of [d - SVG: Scalable Vector Graphics | MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands) to. I’m not sure how well supported it is but it is documented. The authors of Makie might be able to give better assistance on their discord that might integrate better with `arrows`.

---

<div class="post-metadata">

**Author:** ![albertomercurio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albertomercurio/32/27051_2.png) [@albertomercurio](https://discourse.julialang.org/u/albertomercurio)\
**Post date:** [July 13, 2024, 7:30pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/4 "2024-07-13T19:30:54Z")

</div>

Makie.jl has the `BezierPath`, which should be similar to the BezierCurve you proposed (right?).

Although I can use the `lines` function together with the `BezierPath`, I don’t know how to make the head of the arrow, corresponding to the correct direction.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [July 13, 2024, 7:40pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/5 "2024-07-13T19:40:04Z")

</div>

That doesn’t exist yet as a nice recipe, but I have plans for it. A quick mockup without much functionality is this:

```julia
@recipe(CurvedArrow) do scene
    Theme(
        color = :black,
    )
end

function Makie.plot!(p::CurvedArrow)
    scene = Makie.get_scene(p)

    points = lift(p, scene.camera.projectionview, p.model, Makie.transform_func(p),
          scene.viewport, p[1], p[2]) do _, _, _, _, p1, p2

        return Makie.project.(Ref(scene), (p1, p2))
    end

    arc = lift(points) do (p1, p2)
        len = Makie.norm(p2 - p1)
        EllipticalArc(
            p1...,
            p2...,
            len/1.3,
            len/1.3,
            0,
            false,
            false,
        )
    end

    path = lift(arc) do arc
        BezierPath([
            MoveTo(points[][1]),
            arc,
        ])
    end

    trimarker = BezierPath([MoveTo(0, 0), LineTo(0.5, -1), LineTo(-0.5, -1), ClosePath()])

    markerangle = lift(arc) do arc
        arc.a2 + pi
    end

    lines!(p, path, space = :pixel, color = p.color)
    scatter!(p, p[2], marker = trimarker, rotation = markerangle, color = p.color)
end

Makie.data_limits(p::CurvedArrow) = Rect3f(Rect2f([p[1][], p[2][]]))
Makie.boundingbox(p::CurvedArrow, space::Symbol = :data) = Makie.apply_transform_and_model(p, Makie.data_limits(p))

f, ax, _ = curvedarrow(Point2f(0, 0), Point2f(1, 1))
curvedarrow!(ax, Point2f(1.1, 1.1), Point2f(1.5, 2))
f

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/f/df9a0f6a0a28ba425ba88c0c7113417768ef2fe0.png)

When I make the real one, it will have lots of options, annotation arrows can be pretty tricky to get right

---

<div class="post-metadata">

**Author:** ![albertomercurio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albertomercurio/32/27051_2.png) [@albertomercurio](https://discourse.julialang.org/u/albertomercurio)\
**Post date:** [July 13, 2024, 8:47pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/6 "2024-07-13T20:47:15Z")

</div>

It doesn’t work for me. I have CairoMakie v0.12.5

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [July 13, 2024, 8:51pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/7 "2024-07-13T20:51:09Z")

</div>

Hm I did this with GLMakie, would have to try later what’s going on. As a side note, telling me _how_ something doesn’t work is helpful 😄

---

<div class="post-metadata">

**Author:** ![albertomercurio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albertomercurio/32/27051_2.png) [@albertomercurio](https://discourse.julialang.org/u/albertomercurio)\
**Post date:** [July 13, 2024, 8:52pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/8 "2024-07-13T20:52:48Z")

</div>

It doesn’t display in the jupyter notebook. No errors, but I can’t see anything.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [July 13, 2024, 8:58pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/9 "2024-07-13T20:58:08Z")

</div>

Aha seems some method in CairoMakie is missing to project the EllipticalArc. This works, using some internal makie function to replace the EllipticalArc with curves

```julia
path = lift(arc) do arc
        Makie.replace_nonfreetype_commands(
            BezierPath([
                MoveTo(points[][1]),
                arc,
            ])
        )
    end

```

---

<div class="post-metadata">

**Author:** ![albertomercurio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albertomercurio/32/27051_2.png) [@albertomercurio](https://discourse.julialang.org/u/albertomercurio)\
**Post date:** [July 14, 2024, 9:09am UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/10 "2024-07-14T09:09:16Z")

</div>

Thank you very much.

BTW, is it necessary all this code? In my mind, I was wondering on using just `lines` with a `BezierPath` and then making the head using a single marker of `scatter`. The only question is how to get the correct angle of the marker to be the head of the arrow.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [July 14, 2024, 9:40am UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/11 "2024-07-14T09:40:38Z")

</div>

The complexity comes exactly from that problem, determining marker angle in screen space, and connection line in screen space. If you make an arc in data space it will not look like an arc if your axes are scaled differently

---

<div class="post-metadata">

**Author:** ![cmdenis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cmdenis/32/211517_2.png) [@cmdenis](https://discourse.julialang.org/u/cmdenis)\
**Post date:** [September 5, 2024, 6:07pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/12 "2024-09-05T18:07:04Z")

</div>

Is this feature not implemented still?

It would be great to have something kind of like what `Plots` does, described [here.](https://discourse.julialang.org/t/how-to-draw-a-line-with-an-arrow-in-plot-jl/55974)

Being able to add an `arrow = true` in the `lines` method for instance.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [September 5, 2024, 9:14pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/13 "2024-09-05T21:14:03Z")

</div>

This thread seems to be about _curved_ arrows, while the linked one on Plots is about _straight_ arrows.  
If you just want straight lines with arrows, they are already available in [[ANN] MakieExtra.jl – more recipes and tools for Makie plots](https://discourse.julialang.org/t/ann-rfc-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618) as `arrowlines()`:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/3/c/3c091c30dcb8807818b3d9e26efdfc2ad11d41dd.jpeg)  
Even with different arrowhead styles (:

---

<div class="post-metadata">

**Author:** ![cmdenis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cmdenis/32/211517_2.png) [@cmdenis](https://discourse.julialang.org/u/cmdenis)\
**Post date:** [September 5, 2024, 9:31pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/14 "2024-09-05T21:31:35Z")

</div>

Ok, thanks! That’s neat for straight lines!

It would be a nice feature to be able to do it with curved lines in Makie:

```julia
using Plots
plot(sin, 0:0.01:7, arrow = true)

```

Which yields:

 ![Capture d’écran, le 2024-09-05 à 17.30.36](https://global.discourse-cdn.com/julialang/original/3X/5/9/59a67fef8d3724e37196f7dcb0312d78781ed820.png)

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [September 6, 2024, 8:24am UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/15 "2024-09-06T08:24:08Z")

</div>

Actually, it turned out to be basically trivial to support!  
I’ve been planning to fix `x/yscale` handling for arrows anyway, and added multi-point arrows as well while at it (:  
Coming in the next MakieExtra version:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/0/606b2e98777b78228947716304b8fbb58f0715a1.jpeg)

---

<div class="post-metadata">

**Author:** ![cmdenis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cmdenis/32/211517_2.png) [@cmdenis](https://discourse.julialang.org/u/cmdenis)\
**Post date:** [September 6, 2024, 5:52pm UTC](https://discourse.julialang.org/t/curved-arrow-using-makie-jl/117013/16 "2024-09-06T17:52:32Z")

</div>

Fantastic work! Looking forward to it!
