-
-
Save ffreyer/0875fceb4ba80c6779f5ff14b5f24f2d to your computer and use it in GitHub Desktop.
Blob of code to simulate line join issues
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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