Skip to content

Instantly share code, notes, and snippets.

@ffreyer
Created April 12, 2023 14:03
Show Gist options
  • Save ffreyer/0875fceb4ba80c6779f5ff14b5f24f2d to your computer and use it in GitHub Desktop.
Save ffreyer/0875fceb4ba80c6779f5ff14b5f24f2d to your computer and use it in GitHub Desktop.
Blob of code to simulate line join issues
using GLMakie, LinearAlgebra, GeometryBasics
let
line_ps = Observable(Point2f.([-20, -20, 20, 20], [0, 20, 20, 0]))
linewidth = 10
AA_THICKNESS = 2
inner_mesh = Observable{GeometryBasics.GLNormalMesh}()
outer_mesh = Observable{GeometryBasics.GLNormalMesh}()
inner_outline = Observable{Vector{Point2f}}()
on(line_ps) do ps
p0, p1, p2, p3 = ps
v0 = normalize(p1 - p0)
v1 = normalize(p2 - p1)
v2 = normalize(p3 - p2)
n0 = Vec2f(-v0[2], v0[1])
n1 = Vec2f(-v1[2], v1[1])
n2 = Vec2f(-v2[2], v2[1])
thickness_aa = linewidth + AA_THICKNESS
miter_a = normalize(n0 + n1)
miter_b = normalize(n1 + n2)
length_a = thickness_aa / dot(miter_a, n1)
length_b = thickness_aa / dot(miter_b, n1)
outer_mesh[] = let
# Current (single triangle)
# pos = Point2f[
# p0 - thickness_aa * n0, p0 + thickness_aa * n0,
# p1 - length_a * miter_a, p1 + length_a * miter_a,
# p2 - length_b * miter_b, p2 + length_b * miter_b,
# p3 - thickness_aa * n2, p3 + thickness_aa * n2
# ]
# Midpoint (only center piece)
pos = Point2f[
p0 + thickness_aa * n0,
p0 - thickness_aa * n0,
p1 + length_a * miter_a,
p1 - length_a * miter_a,
0.5 * (p1 + length_a * miter_a + p2 + length_b * miter_b),
p2 - length_b * miter_b,
p2 + length_b * miter_b,
p3 - thickness_aa * n2,
p3 + thickness_aa * n2,
]
faces = [GLTriangleFace(i, i+1, i+2) for i in 1:length(pos)-2]
normal_mesh(pos, faces)
end
inner_mesh[] = let
ps = Point2f.(outer_mesh[].position)
f1 = 1 - AA_THICKNESS / thickness_aa
f2 = AA_THICKNESS / thickness_aa
pos = Point2f[]
for i in 1:length(ps)-1
even, odd = i % 2 == 0 ? (i, i+1) : (i+1, i)
push!(pos,
0.5 * f2 * (ps[i] + ps[i+1]) + f1 * ps[even],
0.5 * f2 * (ps[i] + ps[i+1]) + f1 * ps[odd],
)
end
faces = [GLTriangleFace(i, i+1, i+2) for i in 1:length(pos)-2]
normal_mesh(pos, faces)
end
inner_outline[] = let
f1 = 1 - AA_THICKNESS / thickness_aa
pos = Point2f[
p0 - f1 * thickness_aa * n0,
p0 + f1 * thickness_aa * n0,
p1 + f1 * length_a * miter_a,
p2 + f1 * length_b * miter_b,
p3 + f1 * thickness_aa * n2,
p3 - f1 * thickness_aa * n2,
p2 - f1 * length_b * miter_b,
p1 - f1 * length_a * miter_a,
p0 - f1 * thickness_aa * n0,
]
end
end
notify(line_ps)
fig = Figure()
ax = Axis(fig[1, 1], aspect = DataAspect())
xlims!(ax, -35, 35)
ylims!(ax, -10, 40)
mesh!(ax, outer_mesh, color = (:lightblue, 0.4), shading = false, fxaa = false)
mesh!(ax, inner_mesh, color = (:blue, 0.4), shading = false, fxaa = false)
wireframe!(ax, outer_mesh, color = :black)
# wireframe!(ax, inner_mesh, color = :red)
lines!(ax, inner_outline, color = :red, overdraw = true)
plt2 = lines!(ax, line_ps, color = :lightgray, linewidth = 10)
plt1 = scatter!(
ax, line_ps, markersize = 20, marker = Circle, color = :white,
strokecolor = :orange, strokewidth = 2, overdraw = true
)
selected1 = Ref(-1)
selected2 = Ref(-1)
on(events(fig).mousebutton, priority = 1000) do event
if event.button == Mouse.left
if event.action == Mouse.press
p, idx = pick(fig, mouseposition_px(fig))
if p == plt1
selected1[] = idx
return Consume(true)
elseif p == plt2
selected2[] = idx
return Consume(true)
end
elseif event.action == Mouse.release
selected1[] = -1
selected2[] = -1
end
end
return Consume(false)
end
on(events(fig).mouseposition, priority = 1000) do _
if selected1[] != -1
mpos = mouseposition(ax)
line_ps[][selected1[]] = mpos
notify(line_ps)
return Consume(true)
elseif selected2[] != -1
mpos = mouseposition(ax)
p0, p1, p2, p3 = line_ps[]
if selected2[] == 2
line_ps[][selected2[]-1] = Point2f(0.5(p0[1] - p1[1]) + mpos[1], p0[2])
line_ps[][selected2[]] = Point2f(0.5(p1[1] - p0[1]) + mpos[1], p1[2])
elseif selected2[] == 3
line_ps[][selected2[]-1] = Point2f(p1[1], 0.5(p1[2] - p2[2]) + mpos[2])
line_ps[][selected2[]] = Point2f(p2[1], 0.5(p2[2] - p1[2]) + mpos[2])
elseif selected2[] == 4
line_ps[][selected2[]-1] = Point2f(0.5(p2[1] - p3[1]) + mpos[1], p2[2])
line_ps[][selected2[]] = Point2f(0.5(p3[1] - p2[1]) + mpos[1], p3[2])
end
notify(line_ps)
return Consume(true)
end
return Consume(false)
end
fig
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment