Skip to content

Commit

Permalink
move gappy & friends to Makie
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonDanisch committed Feb 13, 2024
1 parent 25b440a commit be97725
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 65 deletions.
40 changes: 5 additions & 35 deletions GLMakie/src/glshaders/lines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,6 @@ function intensity_convert_tex(intensity::VecOrSignal{T}, verts) where T
Texture(intensity)
end
end
#TODO NaNMath.min/max?
dist(a, b) = abs(a-b)
mindist(x, a, b) = min(dist(a, x), dist(b, x))
function gappy(x, ps)
n = length(ps)
x <= first(ps) && return first(ps) - x
for j=1:(n-1)
p0 = ps[j]
p1 = ps[min(j+1, n)]
if p0 <= x && p1 >= x
return mindist(x, p0, p1) * (isodd(j) ? 1 : -1)
end
end
return last(ps) - x
end
function ticks(points, resolution)
# This is used to map a vector of `points` to a signed distance field. The
# points mark transition between "on" and "off" section of the pattern.

# The output should be periodic so the signed distance field value
# representing points[1] should be equal to the one representing points[end].
# => range(..., length = resolution+1)[1:end-1]

# points[end] should still represent the full length of the pattern though,
# so we need rescaling by ((resolution + 1) / resolution)

scaled = ((resolution + 1) / resolution) .* points
r = range(first(scaled), stop=last(scaled), length=resolution+1)[1:end-1]
return Float16[-gappy(x, scaled) for x = r]
end

@nospecialize
function draw_lines(screen, position::Union{VectorTypes{T}, MatTypes{T}}, data::Dict) where T<:Point
Expand Down Expand Up @@ -110,10 +80,10 @@ function draw_lines(screen, position::Union{VectorTypes{T}, MatTypes{T}}, data::
if !isa(to_value(pattern), Vector)
error("Pattern needs to be a Vector of floats. Found: $(typeof(pattern))")
end
tex = GLAbstraction.Texture(map(pt -> ticks(pt, 100), pattern), x_repeat = :repeat)
tex = GLAbstraction.Texture(lift(Makie.linestyle_to_sdf, pattern); x_repeat=:repeat)
data[:pattern] = tex
end
data[:pattern_length] = map(pt -> Float32(last(pt) - first(pt)), pattern)
data[:pattern_length] = lift(pt -> Float32(last(pt) - first(pt)), pattern)
end

data[:intensity] = intensity_convert(intensity, vertex)
Expand All @@ -123,7 +93,7 @@ end
function draw_linesegments(screen, positions::VectorTypes{T}, data::Dict) where T <: Point
@gen_defaults! data begin
vertex = positions => GLBuffer
color = default(RGBA, s, 1) => GLBuffer
color = nothing => GLBuffer
color_map = nothing => Texture
color_norm = nothing
thickness = 2f0 => GLBuffer
Expand Down Expand Up @@ -151,9 +121,9 @@ function draw_linesegments(screen, positions::VectorTypes{T}, data::Dict) where
if !isa(to_value(pattern), Vector)
error("Pattern needs to be a Vector of floats. Found: $(typeof(pattern))")
end
tex = GLAbstraction.Texture(map(pt -> ticks(pt, 100), pattern), x_repeat = :repeat)
tex = GLAbstraction.Texture(lift(Makie.linestyle_to_sdf, pattern); x_repeat=:repeat)
data[:pattern] = tex
data[:pattern_length] = map(pt -> Float32(last(pt) - first(pt)), pattern)
data[:pattern_length] = lift(pt -> Float32(last(pt) - first(pt)), pattern)
end
robj = assemble_shader(data)
return robj
Expand Down
41 changes: 11 additions & 30 deletions WGLMakie/src/lines.jl
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
# Same as GLMakie, see GLMakie/shaders/lines.jl
# TODO: maybe move to Makie?
dist(a, b) = abs(a-b)
mindist(x, a, b) = min(dist(a, x), dist(b, x))
function gappy(x, ps)
n = length(ps)
x <= first(ps) && return first(ps) - x
for j=1:(n-1)
p0 = ps[j]
p1 = ps[min(j+1, n)]
if p0 <= x && p1 >= x
return mindist(x, p0, p1) * (isodd(j) ? 1 : -1)
end
end
return last(ps) - x
end
function ticks(points, resolution)
scaled = ((resolution + 1) / resolution) .* points
r = range(first(scaled), stop=last(scaled), length=resolution+1)[1:end-1]
return Float16[-gappy(x, scaled) for x = r]
end

function serialize_three(scene::Scene, plot::Union{Lines, LineSegments})
Makie.@converted_attribute plot (linewidth, linestyle)
Expand All @@ -28,13 +8,14 @@ function serialize_three(scene::Scene, plot::Union{Lines, LineSegments})
:depth_shift => plot.depth_shift,
:picking => false
)

if isnothing(to_value(linestyle))
uniforms[:pattern] = false
uniforms[:pattern_length] = 1f0
else
# TODO: pixel per unit
uniforms[:pattern] = Sampler(map(pt -> ticks(pt, 100), linestyle), x_repeat = :repeat)
uniforms[:pattern_length] = map(pt -> Float32(last(pt) - first(pt)), linestyle)
uniforms[:pattern] = Sampler(lift(Makie.linestyle_to_sdf, plot, linestyle); x_repeat=:repeat)
uniforms[:pattern_length] = lift(ls -> Float32(last(ls) - first(ls)), linestyle)
end

color = plot.calculated_colors
Expand All @@ -55,18 +36,18 @@ function serialize_three(scene::Scene, plot::Union{Lines, LineSegments})

indices = Observable(Int[])
points_transformed = lift(plot, transform_func_obs(plot), plot[1], plot.space) do tf, ps, space
output = apply_transform(tf, ps, space)
transformed_points = apply_transform(tf, ps, space)
# TODO: Do this in javascript?
if isempty(output)
if isempty(transformed_points)
empty!(indices[])
notify(indices)
return output
return transformed_points
else
sizehint!(empty!(indices[]), length(output) + 2)
sizehint!(empty!(indices[]), length(transformed_points) + 2)
was_nan = true
for i in eachindex(output)
for i in eachindex(transformed_points)
# dublicate first and last element of line selection
if isnan(output[i])
if isnan(transformed_points[i])
if !was_nan
push!(indices[], i-1) # end of line dublication
end
Expand All @@ -78,10 +59,10 @@ function serialize_three(scene::Scene, plot::Union{Lines, LineSegments})

push!(indices[], i)
end
push!(indices[], length(output))
push!(indices[], length(transformed_points))
notify(indices)

return output[indices[]]
return transformed_points[indices[]]
end
end
positions = lift(serialize_buffer_attribute, plot, points_transformed)
Expand Down
30 changes: 30 additions & 0 deletions src/utilities/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -470,3 +470,33 @@ function available_plotting_methods()
end
return meths
end

mindist(x, a, b) = min(abs(a - x), abs(b - x))
function gappy(x, ps)
n = length(ps)
x <= first(ps) && return first(ps) - x
for j in 1:(n - 1)
p0 = ps[j]
p1 = ps[min(j + 1, n)]
if p0 <= x && p1 >= x
return mindist(x, p0, p1) * (isodd(j) ? 1 : -1)
end
end
return last(ps) - x
end


# This is used to map a vector of `points` to a signed distance field. The
# points mark transition between "on" and "off" section of the pattern.

# The output should be periodic so the signed distance field value
# representing points[1] should be equal to the one representing points[end].
# => range(..., length = resolution+1)[1:end-1]

# points[end] should still represent the full length of the pattern though,
# so we need rescaling by ((resolution + 1) / resolution)
function linestyle_to_sdf(linestyle::AbstractVector{<:Real}, resolution::Real=100)
scaled = ((resolution + 1) / resolution) .* linestyle
r = range(first(scaled); stop=last(scaled), length=resolution + 1)[1:(end - 1)]
return Float16[-gappy(x, scaled) for x in r]
end

0 comments on commit be97725

Please sign in to comment.