Skip to content
This repository has been archived by the owner on Jul 13, 2021. It is now read-only.

Commit

Permalink
jk/text offset (#703)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkrumbiegel authored Apr 25, 2021
1 parent 927efac commit d412898
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 11 deletions.
25 changes: 25 additions & 0 deletions docs/src/plotting_functions/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,29 @@ for (p, al) in zip(points[7:9], (:left, :center, :right))
end
scene
```

The offset attribute can be used to shift text away from its position.
This is especially useful with `space = :screen`, for example to place text together with barplots.
You can specify the end of the barplots in data coordinates, and then offset the text a little bit to the left.

```@example
using CairoMakie
CairoMakie.activate!() # hide
AbstractPlotting.inline!(true) # hide
f = Figure(resolution = (800, 600))
horsepower = [52, 78, 80, 112, 140]
cars = ["Kia", "Mini", "Honda", "Mercedes", "Ferrari"]
ax = Axis(f[1, 1], xlabel = "horse power")
tightlimits!(ax, Left())
hideydecorations!(ax)
barplot!(horsepower, direction = :x)
text!(cars, position = Point.(horsepower, 1:5), align = (:right, :center),
offset = (-20, 0), color = :white)
f
```
1 change: 1 addition & 0 deletions src/interfaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ $(ATTRIBUTES)
justification = automatic,
lineheight = 1.0,
space = :screen, # or :data
offset = Point2f0(0, 0),
_glyphlayout = nothing,
)
end
Expand Down
40 changes: 30 additions & 10 deletions src/layouting/layouting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,17 @@ function glyph_positions(str::AbstractString, font_per_char, fontscale_px, halig
reduce(vcat, map(line -> [l.hadvance for l in line], lineinfos)))
end

function preprojected_glyph_arrays(string::String, position::VecTypes, glyphlayout::AbstractPlotting.Glyphlayout, font, textsize, space::Symbol, projview, resolution)
function preprojected_glyph_arrays(string::String, position::VecTypes, glyphlayout::AbstractPlotting.Glyphlayout, font, textsize, space::Symbol, projview, resolution, offset::VecTypes, transfunc)

offset = to_ndim(Point3f0, offset, 0)
pos3f0 = to_ndim(Point3f0, position, 0)

atlas = get_texture_atlas()
if space == :data
positions = glyphlayout.origins .+ to_ndim(Point3f0, position, 0)
positions = apply_transform(transfunc, [pos3f0 + offset + o for o in glyphlayout.origins])
elseif space == :screen
projected = AbstractPlotting.project(projview, resolution, to_ndim(Point3f0, position, 0))
positions = glyphlayout.origins .+ to_ndim(Point3f0, projected, 0)
projected = AbstractPlotting.project(projview, resolution, apply_transform(transfunc, pos3f0))
positions = [to_ndim(Point3f0, projected, 0) + offset + o for o in glyphlayout.origins]
else
error("Unknown space $space, only :data or :screen allowed")
end
Expand All @@ -255,19 +258,36 @@ function preprojected_glyph_arrays(string::String, position::VecTypes, glyphlayo
return positions, offsets, uv, scales
end

function preprojected_glyph_arrays(strings::AbstractVector{<:String}, positions::AbstractVector, glyphlayouts::Vector, font, textsize, space::Symbol, projview, resolution)

function preprojected_glyph_arrays(strings::AbstractVector{<:String}, positions::AbstractVector, glyphlayouts::Vector, font, textsize, space::Symbol, projview, resolution, offset, transfunc)

if offset isa VecTypes
offset = [to_ndim(Point3f0, offset, 0)]
end

megastring = join(strings, "")

if space == :data
allpos = map(positions, glyphlayouts) do pos, glyphlayout::AbstractPlotting.Glyphlayout
allpos = broadcast(positions, glyphlayouts, offset) do pos, glyphlayout::AbstractPlotting.Glyphlayout, offs
p = to_ndim(Point3f0, pos, 0)
[p + o for o in glyphlayout.origins]
apply_transform(
transfunc,
[p .+ to_ndim(Point3f0, offs, 0) .+ o for o in glyphlayout.origins]
)
end
elseif space == :screen
allpos = map(positions, glyphlayouts) do pos, glyphlayout::AbstractPlotting.Glyphlayout
projected = to_ndim(Point3f0, AbstractPlotting.project(projview, resolution, to_ndim(Point3f0, pos, 0)), 0)
return [projected .+ o for o in glyphlayout.origins]
allpos = broadcast(positions, glyphlayouts, offset) do pos, glyphlayout::AbstractPlotting.Glyphlayout, offs
projected = to_ndim(
Point3f0,
AbstractPlotting.project(
projview,
resolution,
apply_transform(transfunc, to_ndim(Point3f0, pos, 0))
),
0)

return [projected .+ to_ndim(Point3f0, offs, 0) + o
for o in glyphlayout.origins]
end
else
error("Unknown space $space, only :data or :screen allowed")
Expand Down
39 changes: 38 additions & 1 deletion test/ReferenceTests/src/tests/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ end
end


@cell "3D screenspace annotaitons" begin
@cell "3D screenspace annotations" begin
positions = RNG.rand(Point3f0, 10)
fig, ax, p = meshscatter(positions, color=:white)
text!(
Expand All @@ -211,3 +211,40 @@ end
overdraw=false)
fig
end


@cell "Text offset" begin
f = Figure(resolution = (1000, 1000))
barplot(f[1, 1], 3:5)
text!("bar 1", position = (1, 3), offset = (0, 10), align = (:center, :baseline))
text!(["bar 2", "bar 3"], position = [(2, 4), (3, 5)],
offset = [(0, -10), (0, -20)],
align = (:center, :top), color = :white)

scatter(f[1, 2], Point2f0(0, 0))
text!("hello", position = (0, 0), offset = (40, 0), align = (:left, :center))
text!("hello", position = (0, 0), offset = (40, 0), align = (:left, :center),
rotation = -pi/4)
text!("hello", position = (0, 0), offset = (40, 0), align = (:left, :center),
rotation = pi/4)

scatter(f[2, 1], Point2f0[(0, 0), (10, 0), (20, 10)])
text!("ABC", space = :data, offset = (0, 0), color = (:red, 0.3), align = (:left, :baseline))
text!("ABC", space = :data, offset = (10, 0), color = (:green, 0.3), align = (:left, :baseline))
text!("ABC", space = :data, offset = (20, 10), color = (:blue, 0.3), align = (:left, :baseline))

LScene(f[2, 2], scenekw = (show_axis = false,))
scatter!(Point3f0[(0, 0, 0), (2, 2, 2)])
text!("hello", position = Point3f0(1, 1, 1), offset = (10, 10))

f
end


@cell "Log10 text" begin
barplot([1, 10, 100], fillto = 0.1, axis = (yscale = log10,))
text!(["bar 1", "bar 2", "bar 3"], position = [(1, 1), (2, 10), (3, 100)],
offset = (0, -10), color = :white, align = (:center, :top))
tightlimits!(current_axis(), Bottom())
current_figure()
end

0 comments on commit d412898

Please sign in to comment.