From d8f224c30f13290223a15aca3eca90c6c6fcbc82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 20:51:09 +1000 Subject: [PATCH 01/17] Curve linetype --- src/lines.jl | 52 ++++++++++++++++++++++++-------------------- src/plot.jl | 8 +++---- test/data/curve.png | Bin 0 -> 33706 bytes test/runtests.jl | 11 ++++++++++ 4 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 test/data/curve.png diff --git a/src/lines.jl b/src/lines.jl index 2122483..fda9511 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -80,7 +80,7 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T end function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, arrowlength, angleoffset, outangle=pi/5) where {T<:Integer} - lines = Array{Vector}(ne(g)) + curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) arrows = Array{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) @@ -93,7 +93,7 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real starty = locs_y[i] + nodesize[i]*sin(θ) endx = locs_x[i] + (d-nodesize[j])*1.00*cos(θ) endy = locs_y[i] + (d-nodesize[j])*1.00*sin(θ) - lines[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -102,11 +102,11 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real arrows[e_idx] = [arr1, (endx, endy), arr2] end end - return lines, arrows + return vcat.(curves...), arrows end function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, outangle=pi/5) - lines = Array{Vector}(ne(g)) + curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) arrows = Array{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) @@ -119,7 +119,7 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, starty = locs_y[i] + nodesize*sin(θ) endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) - lines[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -128,11 +128,11 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, arrows[e_idx] = [arr1, (endx, endy), arr2] end end - return lines, arrows + return vcat.(curves...), arrows end function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) - lines = Array{Vector}(ne(g)) + curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) j = dst(e) @@ -144,13 +144,13 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) starty = locs_y[i] + nodesize*sin(θ) endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) - lines[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end - lines + return vcat.(curves...) end function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, outangle) where {T<:Integer} - lines = Array{Vector}(ne(g)) + curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) j = dst(e) @@ -162,9 +162,9 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real starty = locs_y[i] + nodesize*sin(θ) endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) - lines[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end - return lines + return vcat.(curves...) end # this function is copy from [IainNZ](https://github.com/IainNZ)'s [GraphLayout.jl](https://github.com/IainNZ/GraphLayout.jl) @@ -197,15 +197,21 @@ function curvearrowcoords2(θ1, θ2, endx, endy, arrowlength, angleoffset=20.0/1 end function curveedge(x1, y1, x2, y2, θ) - θ1 = atan((y2-y1)/(x2-x1)) - d = sqrt((x2-x1)^2+(y2-y1)^2) - r = d/2cos(θ) - if x1 <= x2 - x = x1 + r*cos(θ+θ1) - y = y1 + r*sin(θ+θ1) - else - x = x2 + r*cos(θ+θ1) - y = y2 + r*sin(θ+θ1) - end - return [:M, x1,y1, :Q, x, y, x2, y2] + Δx = x2 - x1 + Δy = y2 - y1 + + θ1 = atan(Δy,Δx) + + d = sqrt(Δx^2 + Δy^2) + + r = d/2 + + # Control points for left bending curve. + xc1 = x1 + r * cos(θ1 + θ) + yc1 = y1 + r * sin(θ1 + θ) + + xc2 = x2 + r * cos(θ1 + π - θ) + yc2 = y2 + r * sin(θ1 + π - θ) + + return [(x1,y1), (xc1, yc1), (xc2, yc2), (x2, y2)] end diff --git a/src/plot.jl b/src/plot.jl index 6422589..e6cddcb 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -195,12 +195,12 @@ function gplot(g::AbstractGraph{T}, lines, arrows = nothing, nothing if linetype == "curve" if arrowlengthfrac > 0.0 - lines_cord, arrows_cord = graphcurve(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle) - lines = path(lines_cord) + curves_cord, arrows_cord = graphcurve(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle) + lines = curve(curves_cord...) arrows = line(arrows_cord) else - lines_cord = graphcurve(g, locs_x, locs_y, nodesize, outangle) - lines = path(lines_cord) + curves_cord = graphcurve(g, locs_x, locs_y, nodesize, outangle) + lines = curve(curves_cord...) end else if arrowlengthfrac > 0.0 diff --git a/test/data/curve.png b/test/data/curve.png new file mode 100644 index 0000000000000000000000000000000000000000..b952d6fcd0d4bd8bb51cfb8b0883bc19923194e8 GIT binary patch literal 33706 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 success end + +@testset "Curves" begin + + g2 = DiGraph(2) + add_edge!(g2, 1,2) + add_edge!(g2, 2,1) + + plot_and_save1(fname) = plot_and_save(fname, g2, linetype="curve") + refimg1 = joinpath(datadir, "curve.png") + @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> success +end From 8ca1552990cfd88f379994566317956955283bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 21:18:33 +1000 Subject: [PATCH 02/17] Use vector nodesize The vector nodesize was not used in a function. --- src/lines.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index fda9511..75dacab 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -158,10 +158,10 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real Δy = locs_y[j] - locs_y[i] d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) - startx = locs_x[i] + nodesize*cos(θ) - starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) + startx = locs_x[i] + nodesize[i]*cos(θ) + starty = locs_y[i] + nodesize[i]*sin(θ) + endx = locs_x[i] + (d-nodesize[j])*1.00*cos(θ) + endy = locs_y[i] + (d-nodesize[j])*1.00*sin(θ) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) From 55541ccd1d2e77427d7985d24d6ad746c3aa675e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 22:08:20 +1000 Subject: [PATCH 03/17] Use jth location and nodesize --- src/lines.jl | 64 ++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index 75dacab..25e876b 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -9,12 +9,12 @@ function graphline(g, locs_x, locs_y, nodesize::Vector{T}, arrowlength, angleoff j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[i] + (d-nodesize[j])*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize[j])*1.00*sin(θ) + endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) + endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] arr1, arr2 = arrowcoords(θ, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -30,12 +30,12 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real, arrowlen j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) + endx = locs_x[j] + nodesize*1.00*cos(θ+π) + endy = locs_y[j] + nodesize*1.00*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] arr1, arr2 = arrowcoords(θ, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -50,12 +50,12 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real} j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[i] + (d-nodesize[j])*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize[j])*1.00*sin(θ) + endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) + endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] end lines @@ -68,12 +68,12 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) + endx = locs_x[j] + nodesize*1.00*cos(θ+π) + endy = locs_y[j] + nodesize*1.00*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] end return lines @@ -87,12 +87,12 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[i] + (d-nodesize[j])*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize[j])*1.00*sin(θ) + endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) + endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) @@ -113,12 +113,12 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) + endx = locs_x[j] + nodesize*1.00*cos(θ+π) + endy = locs_y[j] + nodesize*1.00*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) @@ -138,12 +138,12 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[i] + (d-nodesize)*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize)*1.00*sin(θ) + endx = locs_x[j] + nodesize*1.00*cos(θ+π) + endy = locs_y[j] + nodesize*1.00*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) @@ -156,12 +156,12 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) - θ = atan(Δy,Δx) + d = sqrt(Δx^2 + Δy^2) + θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[i] + (d-nodesize[j])*1.00*cos(θ) - endy = locs_y[i] + (d-nodesize[j])*1.00*sin(θ) + endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) + endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) From ccefb9511ff733757b6b90f7ff4a7e4401abcbdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 22:09:13 +1000 Subject: [PATCH 04/17] Remove multiplier --- src/lines.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index 25e876b..aad23a2 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -13,8 +13,8 @@ function graphline(g, locs_x, locs_y, nodesize::Vector{T}, arrowlength, angleoff θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) - endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) + endx = locs_x[j] + nodesize[j]*cos(θ+π) + endy = locs_y[j] + nodesize[j]*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] arr1, arr2 = arrowcoords(θ, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -34,8 +34,8 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real, arrowlen θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[j] + nodesize*1.00*cos(θ+π) - endy = locs_y[j] + nodesize*1.00*sin(θ+π) + endx = locs_x[j] + nodesize*cos(θ+π) + endy = locs_y[j] + nodesize*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] arr1, arr2 = arrowcoords(θ, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -54,8 +54,8 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real} θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) - endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) + endx = locs_x[j] + nodesize[j]*cos(θ+π) + endy = locs_y[j] + nodesize[j]*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] end lines @@ -72,8 +72,8 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[j] + nodesize*1.00*cos(θ+π) - endy = locs_y[j] + nodesize*1.00*sin(θ+π) + endx = locs_x[j] + nodesize*cos(θ+π) + endy = locs_y[j] + nodesize*sin(θ+π) lines[e_idx] = [(startx, starty), (endx, endy)] end return lines @@ -91,8 +91,8 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) - endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) + endx = locs_x[j] + nodesize[j]*cos(θ+π) + endy = locs_y[j] + nodesize[j]*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) @@ -117,8 +117,8 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[j] + nodesize*1.00*cos(θ+π) - endy = locs_y[j] + nodesize*1.00*sin(θ+π) + endx = locs_x[j] + nodesize*cos(θ+π) + endy = locs_y[j] + nodesize*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) @@ -142,8 +142,8 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[j] + nodesize*1.00*cos(θ+π) - endy = locs_y[j] + nodesize*1.00*sin(θ+π) + endx = locs_x[j] + nodesize*cos(θ+π) + endy = locs_y[j] + nodesize*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) @@ -160,8 +160,8 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[j] + nodesize[j]*1.00*cos(θ+π) - endy = locs_y[j] + nodesize[j]*1.00*sin(θ+π) + endx = locs_x[j] + nodesize[j]*cos(θ+π) + endy = locs_y[j] + nodesize[j]*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) From 08339a385e41ca43b1b05e234979d08f12ab1ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 22:10:58 +1000 Subject: [PATCH 05/17] Remove duplication --- src/lines.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index aad23a2..ce07fa6 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -96,11 +96,10 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) - arrows[e_idx] = [arr1, (endx, endy), arr2] else arr1, arr2 = curvearrowcoords2(θ, outangle, endx, endy, arrowlength, angleoffset) - arrows[e_idx] = [arr1, (endx, endy), arr2] end + arrows[e_idx] = [arr1, (endx, endy), arr2] end return vcat.(curves...), arrows end @@ -122,11 +121,10 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) if startx <= endx arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) - arrows[e_idx] = [arr1, (endx, endy), arr2] else arr1, arr2 = curvearrowcoords2(θ, outangle, endx, endy, arrowlength, angleoffset) - arrows[e_idx] = [arr1, (endx, endy), arr2] end + arrows[e_idx] = [arr1, (endx, endy), arr2] end return vcat.(curves...), arrows end From 28559e6c676c2ee7bf7a4a3d8f473985564d3b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 22:15:55 +1000 Subject: [PATCH 06/17] Simplify arrow coordinates Arrow angle is theta minus the angle offset. Theta encompasses the information needed for the arrow direction. --- src/lines.jl | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index ce07fa6..e73684c 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -94,11 +94,7 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real endx = locs_x[j] + nodesize[j]*cos(θ+π) endy = locs_y[j] + nodesize[j]*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) - if startx <= endx - arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) - else - arr1, arr2 = curvearrowcoords2(θ, outangle, endx, endy, arrowlength, angleoffset) - end + arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end return vcat.(curves...), arrows @@ -119,11 +115,7 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, endx = locs_x[j] + nodesize*cos(θ+π) endy = locs_y[j] + nodesize*sin(θ+π) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) - if startx <= endx - arr1, arr2 = curvearrowcoords1(θ, outangle, endx, endy, arrowlength, angleoffset) - else - arr1, arr2 = curvearrowcoords2(θ, outangle, endx, endy, arrowlength, angleoffset) - end + arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end return vcat.(curves...), arrows @@ -174,26 +166,6 @@ function arrowcoords(θ, endx, endy, arrowlength, angleoffset=20.0/180.0*π) return (arr1x, arr1y), (arr2x, arr2y) end -# using when startx <= endx -# θ1 is the angle between line from start point to end point with x axis -# θ2 is the out angle of edge -function curvearrowcoords1(θ1, θ2, endx, endy, arrowlength, angleoffset=20.0/180.0*π) - arr1x = endx + arrowlength*cos(pi+θ1-θ2-angleoffset) - arr1y = endy + arrowlength*sin(pi+θ1-θ2-angleoffset) - arr2x = endx + arrowlength*cos(pi+θ1-θ2+angleoffset) - arr2y = endy + arrowlength*sin(pi+θ1-θ2+angleoffset) - return (arr1x, arr1y), (arr2x, arr2y) -end - -# using when startx > endx -function curvearrowcoords2(θ1, θ2, endx, endy, arrowlength, angleoffset=20.0/180.0*π) - arr1x = endx + arrowlength*cos(pi+θ1+θ2-angleoffset) - arr1y = endy + arrowlength*sin(pi+θ1+θ2-angleoffset) - arr2x = endx + arrowlength*cos(pi+θ1+θ2+angleoffset) - arr2y = endy + arrowlength*sin(pi+θ1+θ2+angleoffset) - return (arr1x, arr1y), (arr2x, arr2y) -end - function curveedge(x1, y1, x2, y2, θ) Δx = x2 - x1 Δy = y2 - y1 From 0d2c328431a2bfcd3abadfe1b8ef3cb950907734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 22:28:57 +1000 Subject: [PATCH 07/17] Make exit angle relative to node centres Somewhat of a stylistic prejudice. --- src/lines.jl | 32 ++++++++++++++++---------------- test/data/curve.png | Bin 33706 -> 34441 bytes 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index e73684c..70d7fe1 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -89,10 +89,10 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real Δy = locs_y[j] - locs_y[i] d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) - startx = locs_x[i] + nodesize[i]*cos(θ) - starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[j] + nodesize[j]*cos(θ+π) - endy = locs_y[j] + nodesize[j]*sin(θ+π) + startx = locs_x[i] + nodesize[i]*cos(θ+outangle) + starty = locs_y[i] + nodesize[i]*sin(θ+outangle) + endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) + endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -110,10 +110,10 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, Δy = locs_y[j] - locs_y[i] d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) - startx = locs_x[i] + nodesize*cos(θ) - starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[j] + nodesize*cos(θ+π) - endy = locs_y[j] + nodesize*sin(θ+π) + startx = locs_x[i] + nodesize*cos(θ+outangle) + starty = locs_y[i] + nodesize*sin(θ+outangle) + endx = locs_x[j] + nodesize*cos(θ+π-outangle) + endy = locs_y[j] + nodesize*sin(θ+π-outangle) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -130,10 +130,10 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) Δy = locs_y[j] - locs_y[i] d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) - startx = locs_x[i] + nodesize*cos(θ) - starty = locs_y[i] + nodesize*sin(θ) - endx = locs_x[j] + nodesize*cos(θ+π) - endy = locs_y[j] + nodesize*sin(θ+π) + startx = locs_x[i] + nodesize*cos(θ+outangle) + starty = locs_y[i] + nodesize*sin(θ+outangle) + endx = locs_x[j] + nodesize*cos(θ+π-outangle) + endy = locs_y[j] + nodesize*sin(θ+π-outangle) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) @@ -148,10 +148,10 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real Δy = locs_y[j] - locs_y[i] d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) - startx = locs_x[i] + nodesize[i]*cos(θ) - starty = locs_y[i] + nodesize[i]*sin(θ) - endx = locs_x[j] + nodesize[j]*cos(θ+π) - endy = locs_y[j] + nodesize[j]*sin(θ+π) + startx = locs_x[i] + nodesize[i]*cos(θ+outangle) + starty = locs_y[i] + nodesize[i]*sin(θ+outangle) + endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) + endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) end return vcat.(curves...) diff --git a/test/data/curve.png b/test/data/curve.png index b952d6fcd0d4bd8bb51cfb8b0883bc19923194e8..668ca01429c10ca9090dcf949700a3c7cdc332ae 100644 GIT binary patch literal 34441 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 literal 33706 zcma&Oc|4T;_dkA(B}HfvvUi6h`@Yl4AY_TMCu2#;l99c-(_OZVq#;X|Y#|L`2G9q{=;qNx?b07Ip=wv=XuWMwv~l3H>VIMf*{;jlVjEh z!V3S(ifr8iKT@tCiST2~IWyy9$OigfPD5b|f=D3PV~1@+AI{LiA39x$+?ZdUpp5L= zWwf>E?QsP&4c#Cd;i(MUy(c;M<4zy{XQbz}*#*bcrHO*))zwRn*L@E8mYG)bKk3h5 z+FIH6a0~9Zf>jB^X>gUE$dNVOVZt&T>?$&^hm=jx+azKDU$4sZ647wsXvBh ziyL^CX7v5KudJ`zoJ`yfV}EdN+Y>V}>a63Zl4Z~`eA-m#?(}(0N1tCFwv3Gig(-zP z`rRp>_8Rh3;xp^KjHHf{(b`40&&Z=X5)(S2zjEVo;k&{^JYC6CB5C~(_|(3hRcIl! zejj?$?ElnZz+We-lQp51AMWVcdhra>B`EGXLL)C9Av*svb%s!%&gXf8nh@Az%JDnG zy*GJE|KvLiI;;GPoXy7@m9LB@rgSH=I)A0cojf}~B$jiYv%E>==v{V4N-DP)gTr|d8$=?44(M4 z|Hkr?+=_7BMrHc)vFv=xgT+UUktuWau2%=?-@CCP=SU>Uc27L^ zdz^p7>d>5qE*A{OpA`E-sZ^T&oY}RO;gRHj#?O^0)&8w5{dz|KXx;2=pnup-m{#-G zo_mT}6Kmd!cLPfpoN2Bf;-_nb@EfMC_T6(4V-FT9(lgm%xJ>zZmY)yFxx2?g$A#nO zYnXOxPdlzpj9zwHYU|`-f%SEzdSe`-?G5riHYrT`U|nhwhIgAy&=wc_95Y1O&>;?1 z>Lb&5Kj(^%nsJI7sd`d(FX>Eom33bX*#Tb%KR(9U{4=qvNuE?;rXzWKy1LGDd@1z{ z`In;K-wU#06)|UG~4Fk8mVh@o99c`>&;Vx?lgO%tX3Yr;$T z!l9^MAcho0Xfmh9{fKm#y#9sE>F*bU4q8=H&pfg6g#0|Kz=G1r;(+Q-;Ivc`QJL? zSr4!Wf`6ZEEFIMT`{gq>@1?67HP|2JZ7WuN@h$T`Z?|1o_=up4gW{7%TG#isQ4?cYBBE&jLRUB`LLzCvj*D|CH7BMA3<^Df9D z0xPZehDTlIlpcs{hPQ!R_sxi)-$lZAy3v8Zv{il&=x!fx%TJkWn9l!#n?N5toneo; z+*>*=%EmQTIj@R7#x7`t?FBQfz%wj#v|CF4f{_?y^yt~4^?N6cA20ts^0NaE=a4@~ z849~xnU3!dH{wU*GDN|ik+O?j?9C3$-e;5qO;!{Sa<%0#Ivx=bSMj6YDkQI{%kc8! zaHHo(-8Ff)&s^Fx(W=MVG|Z%n%GLXSevQ7XuU~!K{eL!4uDu7r&lk1x3%p&~3sd_X zGj5BR^TnK=Sc`{;Ssm^SN3x>vQ%~D}HHKfzn&UA#_fC~xq;jQpX8rF;_S-C^t+a=( z@-?p2+_X)@S@`_5uE*LDk7};9wixLXKecyu!C*1{wm}%Bfp;gi9A1BOY3&Jo^z+~G zK#my2)QhiJ-U-3)Sq`)8%?}k*XRnjh;a9Dgbk63w-MbqCMQM{tMZ9T=`kuj6-!elM+Q0k&MSOFccE{FrCu~FY?p#S?3$) zgHgEuee^K>OUL<)`C3Xh8by+9Y%rJUNL6O@jT;%6upvm97tb8}6X~J*eqs}OLlzcg z`@P5UMd{#P^h0zOhwI{4dT??k^QtIvjeW31mI63(X4zCd|L-wFV3IRq@R%t&{ks>0 z>X^3TVnifhgWybf@$!t-0fiRb=*l$ocsIXs%CxZTSTs!Fxv{D=RsJb9c1c~A1HL?K zIh%w@P#$XEV=FKObc8f#0(}I=Qg5roGeH`Cx$r12*q2sYA3} zWk1DcjJ}^im*{;`T>y#u&5HfL1$Q{|p4W#fj(^=tz0V2J5N#UAr2R_RenaQ-#lZ-t zB_^&7?lHQM-XVq%)u=@hMH&8@y6_Qlc0hzH#s)bnBE=2ArBaF!b4!If>@LLzzRryL zw2$L|{cbwl22*?0&8;RsL+Bnm*SE*X{svOZR-_=fDd$ROF=9d(uJASD`EU)p<_Diy zy?@AM)J^!jKv+_f;NlH0J z-18}&UFc(%+_?;Hkjt7#O8=~!x$^eL(8ZBpC;Fhu0*(W|HexvRh$2`5@lcPr*-*_- zt)lk;qv8wS#bGT$)jwGze0nSEa$8_k>eYOy)4O&TnxHzhK9mYOtu#X#i0 z4e!x!1iYp$8ZL%xXq?TRtgK}D|6HYgN?a!1jF}S)TtXI_o9TZa9A4sxxto8otz0y9 z@YD2Fi?!IAc#*V*vcY|Ddru=jlP{+&u;w>@yh&oJ<%;3*x$$~jZ*NdjXR9k*Aa~4p z4$hSl(RzIVyXsEsZZMHgSvUP<_U9MSl9-z%(U`kcD1=nbTqQ(}{I{SeeXDj#KHP7G z17FBr6HUfk$t>j=3hh|y8^iy75>I!8i6_a<(`F{_~rB2`DCdC;u$Q}L8PtV zdq-MYq9OB7`@iSFRdPDjULYpapUx`+VKdpgrE;WcgeWinoXa>DL$N!ss|b%wGK<9e zszq~}lqlhY`lt81h#Sn;*X;guZbWpN)SD$8+!DStv)8fa5^bd36?F^wgOzX&({t~< z_!t9H`tt45&*Sd-OgJvF9l{N)9k_W8u6g>O@+)(ZXy?bw{0iDTr~0v^ z<;MmFN_orbx*bmr$ZhHE?frBsHdgFXpa$GUvH8kwMCi(_{r&kCd9_@rHx}pA^!-8P z)e}p)8_zqKC#b@}_wKj~uwrZK!VjjJCUEocT+$@fwhzMHR>y5PoA<}g4Tlty4P=UI zh}!Aira1r6V85jsDho1q8uw38aJSM6Ii!x0HuxxVKW1kWRv8Suy0!q^Emlwr&(2y% zSsQYgKhbXC7jpk!+QFJQP0?(!9bs5shChziVeULO!okZ``496w zxwx|b%QmY&*;H5KMxneIdqoo=7g+Xn#KNc1B!Mzj`p>$IF6jcHEqxwnlg= z&reT{JGs$>#r~@gnXO9O2keD)jFjJ&{7w_mFIvZQMLBbZg@r{m@A?NkV8y3_MQJ+M zy4Y*t88MEwo=LFq4avG%Z-d)V*`v2OKPP6hLR@V*H@^j+J(rmz@UMI5tP^h_{tzFh zr6$P^?2OfS_T106yK>72m$yJa-^9nu1{W3Uwb@6D|3*e-wXbzr>NZ+G|_cAG&B^K)n?fB@#Dt;dZTROSp3qQ zeCRhr$7(@}_r{4ad3xh<>cs$&iJ-dSqn$hu!g@?0Sy@XDzufQqsf%aWWtM6tDf(f? zB&o8E*5rN7wR-BK`e?sM*6pS%)BT0`D_3S6KK~xw5&OkhAT+T=tl^#s^&n~E$-R5N zi`5g4(90CvWtMJLubSb&4uWULeQw{4tm{3L zSA!cXZ}UkXBs56k27zhKwCJARUQ)r{jc5qm-m%Z+kff#S*$E1?21SQLEiL26s#5w# zt?~QIzgx@sIF)yDuEo-czcl@|0w!PH%&M`HSt}#1f4{y^x8baj5jk6(m>JN=@iNcfpKPnRnlnPolUXgvU-)sk zq~Y+6?fJb^V9$YQVPtV`gr?q>#5SeNIXViY+WKSp+f_#d%2@{+^5WpmTzxdwb# z_r;?}8H9KI$KQ9`6)HC4mWs`#7j%DX*%N-Pti3()p*St=pRUgt@JpMHdPJr)!fcQw%0 zkNo99=dT*tmCGTuZba?Gg#d13kOon%332PP1YeAFT<&B9HYh4Kde44$L4(4s3BPUo z_wRSUB^vV4NH+ECH2p$#6W^25(=VoK<%%Vz$n>aEVx(e9d;Efi2UxAF407_c4Bv5*H@y=0G~_E?Lqj9voJiY+&YAaku5re*>aaj;O~xSj zXvlI#of+&p;mGE_QU6TUo_P3)qR@F>#a`{}@T~7r!G#Oe8|_C6yOn*AB z^r#@&)cUJa)PlS=@#wYlq@x%}XpdsNbB{dwDXB`fT-eYKP4$Q#q|qXGDb|(DB!53j z=(@bD+9xEO;3fIJdV}ZXIFU#^d10Wup{AV(r@)besGWLbrPW3$uTXmCNd3hc>5VfC zST3}$qm2IR{-^xv8^@{>Cr;ES>iv2fPtN{9@9tshviqpdCG;i<4lv1V8MO8LP73(& zlm!4X4cLp^bCrKI@X`J^ljRBhVv|SliVp@&u?>5=D($K7l(x@hd6}CCiHbT84Gh$@ z(!|f`ESh5vsB8D@p|*K( zTdfu`eA6omGyh$I!Oqw((-V7kaj5C&gqc`cb{FG99xwSTxfG6HQW=q-3a3XMg*`h% zUGAM)4Bm~-ksqC-%$-)LGQFOO!#kY#+UC6^uZVl&MjInb0WF%Orham!-MJwlXj<6o zIFZd?EyKrofbH<*@tH9bSp7QN;gqj>U`pvUerL1cQXo+VNE@ z%4$!e$Ybl`LZBqml4UwQuy_8rQptu2>hIz8PlJ9-GgmoUUznSli@d10D2 zMjDUk`+P0l?#72RkF^q;XnlRZ_35BHJpE&Zr03hpX6|j9$IHgA$)>bF`7hTykJwQ4 zYS@vnx@w@NtzG9#o#%M4l1y&epV8@}zwxFht+KL`sg-D%H1@|_Rre@^%SDyx9N|F4 z;Wt8du#Jid3x9g%{yH{rcOYyGn>wRdI_|Vc8^`dl?u9tw)k+7Epo%|HMK765X0gnj zk$qE5;tPZ8bmj;!CD$(1?~ZMsKY#u=e;d}`l=|n-pI=i`Q(j$kDJ_qsY^iO>&d5$( z#VzUK2TJTpmyVqZE+vmjOvNf~uX$E1_}6ZCsXE$B#Wj%qiR;~!vW2E**3v114s!gX zMeD9&%f!KGb4$w&sqRGoNYb27t^1OALVSF%Xw;uC+N!#}6tHZPq$ttoo+qJ8nG_^h z>>xMdD95i^$LORtYG-tg+&4l4lbamImmqWJIrg3CWRPn3ap{y5KZERUw!=H@wED8l zrGuUlS7x5&YIZ3suLP{yzw2Cv05i7X+L=4g+20)}?U=a0zLZKWaB_-$`r{2x?B$|)k zHSTvcK2_yRZNAp^g+Ad)8k{Cz<4-TXHMlOZwJTs*wYtek?B{$X_fva@xaR6x<~4cT z>3{{0guQtfOW@4tMKh8))9?4mq^ z8`jS)1>|YI30UjvE4ANHdwGEsiQ$w%F6KDMHGZOvo^k({;x5>zP-*0?yAr{aP}QYT zVx_pvbnM#o*(B~)oum$Q&Rp>D@TmD!dkR6)Z?W`j0fyB=XAW}iuZeXJ4Lf(OXG!cJ z8_6t|Fmm)~>0sv@&EP9noK>~7{w(}k4ju%q$#wI{J~h&jo5?g%_!fttgsWF6V%LKt z%j{I54c-u*rw?-DLT172$uRo8CczCF_3-mYKr^!#g@<+u0QMQJj3vS#Sr zS@LY%eb+`+oc(n>{f<$q14LX?I&pKBll7342=T>e>^y!7OZ|M!0KY5%8>@Iga9f-S z-|+*cVOjYTreTRZKmQErWF!ZZ@-NsFe@OEh%>k;4p1gFf%<7Z;INrrN@`jy8#`-6= z{qD&_eJ>IdevqrwsGSZs!r^Cv+6-_6a<-9i!iKq`dTb56!5B#7E8q(xi1 z=j*AfU-{Y7)AJhZ$x^a+@7}4imFHTB^r&)T=7EE~pUqkcjdOI@A3uJq{=)$83Dx5? z%D9X_#2?pWeRK42J;O>Pqe1?qL-WI9rxwqvhBxMO4X>{dcrN{vYLj%Hr4Rf>gFE9C zG6efLnjAci?(JwNj|< zE*X^aj#bUnAlp!8>-7mTgR65U0((d(w2mwlshl{b2<#%`>TYEurx%@HrGwsUnx?&A zo#yt}`*(A(NjB4N$lU3tjO?v7NpO~3w86T52AwJ=1ulO3=FOXzDJdzuMZdad54sC7 z|0y;%qN1Bm^8Cz#otC4ibD zo{{Rs(Z=kA4CJ8Ck1RdPvXeu(K9_Q%<04BGjLZ9%I3 z0R#J=9bU2v#afHBxhtd{k{0Ch)}>zpG%0Kih)B*)!|FW7qzx)e$zro{O>iuBR>+VQ z-|;+xto*{&D}u4v7P7oObX-UC-tU1c=TyUs^A8NH?5ZRKp|As9Ah2c2mXLv!HK@VF zv-HG*|KhO~rAogVm9~$j!!lF!o|$_ubv1WLiJqD;Gfy8>2ezuW{k8x6GiAhxdL75n z{Nh__M59hJpAm-&Nh{OBpXc?@&QCS|(IsR!Dv1k7|?t^GwUn=Gm7bmr~( z`FVdo;N?zjL9ED6VZdMSbLYN(27u$R{W2lYHm?jpD0){syPQy7Uf!+6-@n(Nlbg;` z2TR7X3+POe#Mbh_ouR-bNu~nf{Xl= zUCG+qH>Wys65HXQbGRk;5qS{I1mH;S^jm5p7+AfkyZJ&$u`bWTv6_ndf9Q2|LV zlj#fyXLY97)|AXBrLF%a@Kp5r6n4&Zys!to;}EBjFr*GHb`D-5Y%fXFsl{=&{g|Sc zlarIw#>U39dd9S*zS(aEsrEBnoS2o>=Ce zA&MOnjGcRTUZsu92=db8nREQ?!<)Pa%nuKI=_DXj9?vOQ-t|J0s+v2NEQBgBKZKt` zIfvCWsdtZvSStd`HIOk_K*)L?)4PSBaCw<4SEk;M$`L{zUb%^eov`!ZWC!je)s;sc z?MOfK=+)Z~@bA~7M~`kYHFg^9t_|OD{CyB*rjyWRAIYRN8dKZq>+21weEUimKQ0>} zMi~&YD&N0aVD(tsO@eGc+m0v&bC&T9^}*Wi@MrduNx|n27EWdG5kN=vG!e! zPBTk74|$OuY1k@-JGrN@g(4{RIw_q}r}EMS5dwqG1=ic3_|RD_*h17|ui0ukdE+Q- zh0g|O`XIxzrxp_o4*JZoSnM^a2Z7*ru6Mqb z%)@E=THsbhN02>d{bKR270etD;_dG)m>BE+r@pwjxX`rTJk^!QA?`PBsrp>y14aJ0 zwD`otkb!;DNKVU7$1Dwd+0?9^ZS%{r@iXn`Rc=uX+}Vscf|hfDa?jEI(`=KBqel)- zxqj7RE;}hKTWwAg187_0(U#b#4>BJixOwzL9izlgLpRG!4mo+hd%}|I`ezlafbW;2 z2)OsPv$M1Kc>7_bhbe=IO5DkPkw1e*M|&J;uv=1an^7DvGRxaze|RO=lk@j*>Cui7 z43bR?MmFiu%|cd0jWrz6i6PnzbGV@f#9th&6KM$s^kaHjcZlM$-)CPEyMYNc16Unz zo=klNY9Bf+Y=|T<7R+#FLNg-!V{R@R?9CphQs4NE`M+KO;uC-{YBiS@%^K@JRO3II z6xZ^#4S4YLyES`QkzK93a(KW>bg&RE2UFY6^Qfy@%I=Qox0m6wAVzllJS17bf4Rg* zm2r=};Vc-7A2=w6-Aqoq>0YZ`tcMI)LQL05HC?|=c9r!RWU)}ch|88u z>xjA6xCrpkft2>OY;fa3Y(0e*tvu6NmR|e=^nb0r5|oVSj1rsGbf6}hS#ZDiE|)dMyo0- z2V55QU_r)jOBspgTFK~rqFj2S^sCfdnsgmDcD%$^79Ijz*PdYE)Lb0(oxV}!)t$v# z4(hLe!!Han9?R0RPg+`I+FGGW}EJ-uy zwh{Hhi91&N+U>iOyD&}MiClK$i|Gn7?U>x+ss*OK86B4s0e9mDv z_OQMD1YoQG+l&JVWn<5|0mQ^JK*TVI)1OTtt>ch=g^T{^6*6LFS8V&^U|L6oItgzU z_Dj!l;Vv=qBZaAuX)#yqWq>%$IIw&;jN2eQspZ$)%5oor@h%G1(a-F}8H%yJ#L}5w z1hI#0K0JZTHEjWUT_@a;B1KN4Tgs$4`;~_*h{VpR;4n)N>HL8jU~x;`1nG%@^uo?d zd`uTmLrO>XV%(H-k>D(G+m*GwxAT#hGl%TUhl%aynU*4L>jVQCAA@eDVGBj$_^DvP z{f_}x61O68oZz44fZBbuLp1gW57X0iLcP7cUC%v2KA+mmDj_$l$QS5b;N!)vGQdEi z$B&;wl<>otNhREU`|qRWzva(7lgzXgLqeZG4mJwvM%+13b4f#4&`j1gJpjLiLA>ihgt-9Q9<=0nPIo-uPD<6rI%a^6^XBd!BD{zWKYNZU z0LP9tWw3TLCDm>m$)4k|lEjos=iKeX0uKh4WbP;^LQ42UWGAA-!=A%h7v93Mi8DRc zaALuNv1x4q5zq3YQ`A)3Y!*$zY(&~xWbU|FZ~Tk&Xn$lIzGhlrt&=!*?q+hJNZYM% zfpxcbaj_#ofE%*d4SQ7MB3 zx&HYm;dJNN&s(&08k#~eZr!>y5e8Lx9e%SIox8*q!gJfb9^y#MeNb2$!T3{qnd=zx zMCc!D)$r~+dk&p2E7)Zwj&Xy92ib-16NF_u3JM7g3B-Q+PNUIS3FU-uL3+m(636EF z<64qH@3XI0Yf4INidnbbeGk-? zq}jN?sV9@`xR4xqZeHGQ(DUo^Q|Zj?bjGtBuIm#20Smeyw1XEp3)$NZ;^49@ka<1? zxhTK=wJT&X13-!I=g$V|ty$qWY#&+GCXz7-|87n+V%=eHrdXKCav^Hg3Tce443Ky;P5buL8IC5_6iED8OEeNu0l*v+KxrN`|zR41^MOavP zIvY4v5mDbu>{fJ{lY(n~*zX_N{rZAP)mAzZ{1imnNNlQ06e;5SyVQlNbv#Jblb0`F z-d5V)txOs)srOI3m7QiifY8k;ycm&(`urDqSFxdNlgfmI8o@*)J_UpxY+IeP3l z@fBFX>)6=X@kJF;#M}N9pT0e{$xJ6ip^Z3bDcJz}+VJpyPRLz8SZl4hw5q}slXL%J zRA9t@$Hd@ZPOIR*Jrsj-?H5KAS~i`Y0TRzZYl5&1cl=g_`#4MtH%@4D^^x9$CkIN7EJ^3G}SjkDLk2u)Y$z3@*qb6R;de!f}j)$j7bQ5lab3JC=U`_8bq>G@|<8 zo~z%%I%jyJ;?k`VWu;TyaPI93cikgfNA}7f1Hed8-*jF_VB=fu{kaQjZ zM-jQds7ZJiq_rp&85ud6lq-Wy<*9_(=L_SO0ZVC=as$KfMn?medbNR81&Pf9)PgXU>Bu zP$m{Q(4D00VRuV@5V_BxB@&TiWr<;(hPb*X_KOrjA-O7?=T@W6*6VZQ3oEJIceWrw zM=%b@h8w;bAXxChqJOr(E(L~lH~*Cr57gS!?&PMa$qFDJ?yx-lFWRf06Nqi zvzrLAQR*P)@|7;0td@3#>6)3I9`+q%n;Qx5*b$Cb{u2Djkm4M~I?8rF7$k0M!Nerq z1%C=&-iK|`771a_CcYr(7){Hk_coRu>C-N?dOmjKr)Ba!Kr5b0@tW zj$+In0*NZRnA4DIHDSm_$PN#K4xrKaXSEI=?(k2oTx01g>9nstz&w%F~=n z3jF>q6Q^c;)(Ei@fBpKkDoCf@!|Qg0 zrT);5Hk~uA*2RmjPT*LdhJt520^GjHW^mQdZ)Ve-EdV(-4keDMO401b_HjT~+X5T2 zbYh(4sTO)UaGzWGuD0nwNV+X#cn~>G5`!hymeCkq9>J0?5H(5a zz?H&5Hubx#hNi+#O$vIaOsJ82PCO|sjcdEcV#EpuUs1={TM`-cvzIdSIKp7#2`sK> zPzH&+M{J?H%=;JtDkEx68W{=J#UFeKCobrH>j5PJ5+wl*6@i#80H-%4@~kQ(65$;S z5;q7@yn9T`#UJNdK7ZE*zu{Eru+|W}g|#Oc#&qCjAb~)9_0^JPwZR>!H#w08`{}#;pBuMf$06R49c=nv5 zRtSHcZ%52mt~ulKH##%S%g9K9HXH><_|tN5ess$3`MYLD$YX_6k9w z&}6hc9}L2IY~RFhxb{ZP7S^JFS)RTn4)WTr@CVfpGf|vr_UC+kIUFj2K7?E$UhSa3 zz+ayVtf!u$+uI0R0R@1pkY&e1;HIkpsYn(uie@lOIqaV0i~8>lf>;&%$-gP`I64hW zK4>^eurn~!g)~2g6-D2+fHgf;a{2wMs*b8q5bXu7X(OD;Z4~|pF(PQ#twj9yJ0IzZ z0I+)$KG(2(lfcYtJ$gE|<9jk>Z~A4)bx4%}Cju<{QtG1B&E#^Bk-X4dzU=mYPV$?e zP%(cuwb<5I@=mUY5RuD>k%Jh4_n)P9+O@`}yk$X(x+q_jwkxJAYO0G-6{mDh@nwE& zc0h*M*b#yxUL5l6Ak-*|PC_mkxZG3{u%?CG51WvG0>{#`DudjWEU+&2w_hEm1nQk+ zfwnc+TSu&aS-{!@twdu~MNOcv#t1r3TJQ{mFB_*R6+6T8QDJK5J*llAYt+Yh8uUz@Y*_V(|TT7I=u>F zTAolQm(es(@PX?RMYX&}yBMGz-h@beXn4I3>`Tzl2ZzH!ZB4)6J?s`gClb|3J49!_ ztJX})$K+Il?{u4l734?u;b`mMpeR=d4CJ+N_I9Jv92iuEXf8P=kczV|=Ie+7F#%0k zw_dj|dajH40x6#6b2KF9!QpcAL4O3XuB2(t12D#m5No3iwq8#weZK3mDFosxV`F0- z!Z6i^Q=s~lH1HZxwQsXw5IF~(Oy&#nMwag^^Z^ zmQzf|#4II4`Xe>9EP1v13_kj_zyDks^iNp6zJc+ER|KM7gU|k(uY0HyDm=reE&c$a zVQCr`lrT0?%ZRSk9o-qj)6z5?DxzBYeEZ~8^yweqOvP15hQ*%!G}lwIsS5tV(n#lF zO!L^AfQX~1$rGrGa$wgM#7YwYmzB;OsHW62#Enla_Mh-#xvR&Ch!xhhU4ip$FX)*?p7d2mxld8^nPD`@L6j zkE}wifte#$yl~J@upW*JapoQ~yDm}t*jBdeQm7KbZ46hV<&MPsTe9)_l=vDJRwH3y zNE9@+wO6dMH6N6sOzNDNzMw$VgMFy+vm=%=ka>|A_>%a_?OTzdVYHkA;*R3Is)nH_ zL{U$iD_R8J_1_j$11ZY?sv@DvD9gVN4M|==_?98O=wb188R{fdW4<)jno!J^i}6M{ z5uUfSLzf^17XookA;3;~KLoMK@bHd@hoLil4@VoH2N zPe$M%YS*F|y-Qt9ZSgWdZ=58}`Sl+&;NOmUsu%}BPNYOgSeR@_jZDP>Q>z1dgh={9 zFN{}!NcMrLm%b$260hFgt=<>;5Zh|B{>`n(4!qQeqvLzvaeQ=LK2bLB8Zk0m;5bWJ z97{~Pt>c#SIIp>nm3fMwM#X#sNSKyf&lWn7ZL5&hq-Fpu@b5tYhTeO1&|~W?QpGvK zdO%6aLNj@zAgH(=#y8~-JtP)*;c(@F_{Ix}d~Ec=Qz_^M1uy$rUUTa_fXJ~xOJDSP z+-R}J1ieZ0_hTB&C2)kCVpL}Vk z0vqPP4eCKD(fRD_$(KMT7G4|_MDYrW(dSedVX4Yu9FQ5CfP71(ZB)m;e+n-BE0%-B zY7Zp%U+H~Im?x-ouxlGw>^3x8_atcaDXp$TCrJ91HjEWJT&AL~{+k=ikd0q#4On}T z{|gGl{?KOj7*M)^5MrBgWjPwEjCE}1Fk0XVb9!Wp`Jcl-Lzx{0MP#q0DsHop8BlvIDXtY+-Ns@VX~q>Ga-NkbHwsBu{zE z?q&$nYoRq+dw$E8xpP_yeQMydK|jf<1oikVHC5GxmnSALKbvHb2WilTP+Ib0&x1k? zrui$>Ob$?HZ2HEB*Q zcix;rs%f`hsD#^281gXX3BVmbnl4{6{7e#cmVRibT;GDlpWZutXY5Z?sG3ZV79S#q zV(Ojz+E;I>(2u8Y`1eZiXSW?}6$IOIm9VdkkqoBPZF98B+k73e1Xt75sDiz!WF?dp z@TXZ6YMO;va_3cm)vT>!)DU)rYn##r83wh@r2yT_5@2d zIR$vQ1H@Z_l6aA`3TfRIn^&SLOfBP(-TM2SLzEd0?0FWDQxJZ?%a<=7v3^9|4xt@M zy5EV5o}s7NWdtpcj?2F^iado_3D8|;6`JGF!uF>5a{)6qlw8MGYvVVR6z{YBxWy7v zZ&G002R-O$Q`(u$bK%Bs9K~;(Nv(W6rp2r|#)651>0e2lg0Vul6d`tiDSHy$sCi%08;vZg)G~7a(jui2}tpAAU!x#7-afm9135}SGI`si8eEtPT*;7o(v#j5y^KK2P3ws4plvh^4bO1Bx-SJ6Nk(itN`o6O z?(Igf9VI(c}V z*H^GX4!rtes6@^UE5r(q8^U1}3`@qfbzx5l;&aO06saTXs!( z%UXp#vz2CO@A<6ZE;o&~gwksemJuG0%@bjnIY!|7!penWt+OzbAVY`%JL#Pk-wqat+P=$hdO$Qu&ANI#>#O5V|4VU`=9+-$G?Qg zDg_`oFW=IBuj4MZmxc$DIlPVe5XnbFx|lAsW7$-48-i+w*Y`&!_8Vqs8#{9Q^0M!=`T%J2=Qa%=4K&h;V}@v8of`%vzL)Tpt%{2i z*`*BNGz!2isEn;JMZ*j$AdNqE^+;-^Cv1HKIv_-^+n^kW_0XEmdd~FGFWqKiL4yC4 z*vhn}zP4+10b1OJ9ykvy0p!j4l6P-!LnDMU`e@O8nHHnp>2t*@I0(hrt|}Pljk){4 zmH8{pHDxglHMJk8Vd%UeNSQIQ)MKfYUXZNCp+~L*^HbH+)7$Ukky^>E_lz4+5&*lk zIlSXV!O%nUMlV{dmQ=x%#k0g5Bc7@DG_p)jPp_ANoI55Fu%ziL-L*m`Bp5_X;oaNV zs+3?nDBeX$6gzmvqX46=N-|7Uv+*2P1nLxcBsu0j0D@}7W9lt>)X1jRAPau1`mcK} zjbd=d(+_G>s>w!1ak)s&UIY1qq)Rkv$hgmrh(rMGV|U|cbh z)|ND|ZoWc(cS zHM+nUSm4>Z!0#4VSCsNpct%PiZjC@*UCo9ZeOf6apeP1hh9i0mn?E(&FogSDD0k-B zw_%hB>va9-D~*<&8nbIXJp(TxKZ6lF!7F>gE3W|Fqq>#fmMsXy5lmqeJLHTGnBF~+ zWG=I-2cT9h6V-qMA|DeoHK7I3)|v>f!FqzMuS;A1CF{`vdGqR|RSsy%J-de2QwU!< z_dA1R$7n!VoKE-R;vz$mX74$Z0P4vk`s^bZBQsEabcZ8tQY%NjRFz;YptXysk)lgf z`UTitx=QZa>b;8-IeTIU+lGthw_?B?MO4|!**`l}J$;lA1)g>VK)p>0&|?c+7)y*i zOjRt2Z`gNR4w^@+F45{6fW_Oj)&r#;NjH(mLGgC)rfzYdG(I!4d%|8i8Nv%u`oMvT zyNh|Is<@?9R1=YZWMY&H*B;!+ZqVgTd7{w05p7slA08IF*XsG!Etl_I%PQBgBdJ}# z!Npp;U-n(?b+h;rC+~STzLXq4B)!tAe!J-Q&NM-#xEr-Gxu=3-klZCXyFv@gqsChf zx4eDY`D*d>#LBvIg5eut$q#yojaifHK#Sprpsu=#3vTsvgNX%gC`FU0*jQ7@6_20q_PN=lWl@T(P zf=F_x^9g&=Re>Dq;Ve@@E&dv1973wOj}gSatp_3x#_7zmBu12xHveqT7wTOeUI_;>;sXYV<5+T3LIazdqN zs_FMx7(YFMB__oFg7VMZ@Q#t|eNzCIfwT3&Q(ltmFNWfY4I~FSF@m*Zjt{K!0@TXw zP3kL#;>jdqRUr5G62_t@+}!$pxa?x})6gt(-&6vI6cQJQ zcc~ltpkhMH(75;mj;MzZj;;anKugo~5)BXBocTeBD`x1;GxY2y%Fow|@)EDNJEQ@W%XWsbQ0OoG&v?V56Q7vb57`nG~;413Rz`f z8cq4#eS(MXb$s_K{Ocq-M+9SEqjVR}6o=n}G)G8bf1SdnptJjW?<=Zx7_}*p%r3<1 zf%3#<1L@l2S%6qCLZj`)R!Ud=*q;yg{=q=)%BT(Az-Tg6ANe3NC90RU4e^fQHTmVs z>UT83V)I)eq4dDz=qJh=JKE;8i_v&k294cjtEXYohKh+}yKU~UscmORGRJ!%x(b^R zzA0LRL^yel&U_@ae=puk*f&^&6VZWY&1fU4Kq<(h#SlRj;qgeltwA=lhRCDShWdec z797()8Dvt6&Q!)?6ZVF9!Ru}r~wF_T7`fm zI8Y}p#Ov!Pjuk#m=6Ik8Ydmd`y>XxHUj~Euk3d$lbJJuCff{15y?r=>UR& zEh|*R5K(`?gCGLEOnJ#`7=#$L<^#SFQK8Y%8>Kc_7RpZa3LHKbjy#0&=$6=OtQuf{ z{Q&gErb(_p0ngcRhec?^A`U@3h_I$+par0bd=vgp+ zZ3v);o;cP0GQe*X3VF2I$)*l~9mD(punpyXP%o_%6ub!fOL?XD``o0WR%b+&!9{05 zka3UBboFJ^AqTKpmpVuw^WY&APIkn3>|2T@yv&o|HBcJ|?_E%D%?kXMY}}}l3IwcNZ9y#k5PF|B=obg_`L-27%Y<_~#X!<0 zxAh|<_SUWNUi6U`bg1>YcuGPEVEu8`FXT76c__8Yj|Tia=jtl%&jIoMj6t?|YH(!r zUe)m3j#hb@V4>C5CH} zX?NeBH9Q9g2OPvURAb^g0{q5UistAsGkc0pG;MRZ!MdP{K0?$PkC|oaTNc}+ASNg& zDLr+h8vDlo&KUf=zXsC-71{R}TTq+*iuRkPT1$S8kwF}kLgq%+vG|SSC>Xzn%)!F+ z&~7A$EQ$Sf#x7d*vMW6CLhn0PsIwwmtx%g-A`Xsz5S)e=xx_a^<}_3&L20x0h;NJO zu?FoyX7}#h*{O>uLLQ0-`QyAcT{3dG;m0{Q)edOu@I8AqrY#qQl)V74gkWr$wkqR4 z^1=oO;?_SLndj?g=v-`D%N29~3l|SRst(T)?)2d(epjIJ^ol9`VI5~^hn%^xtcbD( z`__OLYGvll(17vu^Mf!1g8|O+cw=tK$USMA(;eQ zwDd;p8Ip7YHafL?!q|>cJ=;N$Txr_83WV)nbA-nw@oeytZ3Xra@6W9uvs4ikm+kPr zcNfRC5=ooaB^`P6^AHx4P~gI52YG&8fSvPJjn*Cro3{t}b%9q-AH*HW0V(bQ!SHvW=8mLpj(B66#Fp?O_cBuGn369K6O6C?F59h!_-zGk6R|I zCY%9qOy|ba%r{PZj28e1-zrGm#wE;-gx-UAChudJP-ze472KwGJ%YDD0>St5qu=Kq zS2R1s%df$S{FK=Y+Xhw_6tDzK;D*bOcWgs?*tc+Sv<k%>;bHwBASVlM zNt_`4_pl}kQ#rT<*x`?GC~a@rKa~zkv9Poph;V{G9)m?Im1e6JsFNHw4R{)J3W>RK z8Fcvsd$2+-=y*7D@Hp&>7Jj2!Xn!HR(09-FmD|f)1mQ^To|sc2opp>lyMrzJEB8wz zCae}-jh`)3ehru-%ZXUElsl6R+;I4QLB~pH8aA}t4>AM^vaSX~;~Dh8h}I%Z91%rGDUIllRKp({g zDScar>ICkCEiYN#r0vP!0d+IUmcjk95Q;V7n-*D)QcRedZ~VOAj`Ua-;r zR2|esXy4S=NHB-Qd#OMuJ6q)cHTLE4Q10*hQJ6SUlL$Wk22z8L`T2KthlE|cz?BggAlHc{{_5J@hfAz{U&+~rX%e`Fpb=|YL zD;=K#tM!N0vC_QtE9T44&~V<4Sk$zUsyWVFKGVS>70$kgTgS|V6s|^yaZgaICEd#E z26r^}e~W5;i8VO<$227p0q=HN$@MMAm*B32*TBH0PE8Q&brqo6ks`tvHQCMo`DFKm-G*4Vh;iJ-(~`W+EtizM~H_PmMi%VVsS9-#{8qJ zRAc)FlnCpvm0|UnbL{Opb-6@&OA{$ljmVepGu{lVyy~Kz6#8o`3!d&>Tif&7@N--U+DppjDFLbrB;DpLbz6Hz!A~g z-YELM_6~xJsNYq%zx5a*xb%a?;Ik93n(ZkoVo2@Aw(G7L%7#19FFn$$!4{Ky_VY( z?OR3>YBv+=$H?-q$~y1^`5~v>fRdn#`=V|qibVVh zs0+^J`0yTUUDGs5I4F`|EXvH|xl?^iIYViIG7)Z)>ouiQZ+mP8@^$2PfW&%g@#TOa zrO+p1HaKZ4zjzs==11uM`#HPX_Ea-lyA-Ku!s3GS`D-jMBHmUtQGU=JJM<}$Vjb-W z6>@b0eX9hd{tvqeWU?2KQPoyATFj#)W;{0=r+D`}BF}1LeK=Y_XyV||yWmMYSkH3N z-kr+D?CUJ4slegfhV1+pWj2`bE@>9d-q$7EHIwx*P>0H@+ukx{%Mc*>ii7P4e zFQU|db1{!}TKhftSD~0st3KL#HZh(B83Auw!v)U%C6K1V=@`<#bkMh*iryqS^sf-& z_-@-wlXp9Y=7>1H=lbUi1LAfK1K(36Dy!e#WK?QIX7Lhc#?_Y->K_w7z(IXY8}F=- zcYcM1=aKNtahgoelCth1)@tf)XD2O&T%d5~C5&;i{tm%1LCmy*q5+*;YNGVvKPk6t zW(*P1n*M|TH-mDn`r2gQpXenSi08EkI2FiaKA6_Kdcl~cdl0izo;$nlT6y(5_ROX$ zs-Lt)#3isX8$pV2n&d|v<%eM`@M0(b2V6hXU>7sZpJj~TunGYNU5ICq)@>~?8sHP0;}Ii3eo^XQV7wLZZowjXb?z@2zeMUND+Y8hJq$N8XyeBBF${AHw-hNg&jilS9h8 z57WtV`q-g3@~-h7%H@(2`gaLUTc@I4R+Z^uy1tf_k!K#l_mXvMmxe~LrSK)JscAMV3f+Xp{xh`oSRt z-bIT8b*hd0AMp0OM0{02>?};7@CSWA1Dv-Xg_d-Rkf zeR2Ihz#&B!j%&m`#(SrneQ~|Mj&2(ZCu#bx*h%`P8FEL&)ZgAXg-MliDm@ixNVe( zY2P(h24?J(&okYmn^08Ha0sW!1^zP)XS68u{Q2{23jOBo4F%yzI83`^`+Uua z9UK40e{DoQpdPm*6NRb_LrlCV-CiQw)MWI@9FqJ#+u3j!m44_n=Pn$fXeX5Dk z^@tkaFH&znJpND@EA7+!oTi7OQp37FRW3_J7fiNEEEmm$tluauj2Vth1H(JbJrZNMIYRub5%$k{;$;*HPr|n%u`sXyxn@UV0}VmWo2F*WG0!t(lFs*b>lGS)?>$RI8TzaJgm9TN6oy$~ zKQ>R$5Y$(DxWks3;ZQ~~H9HO>g@1i`hoBk{H&TCKDbMM{vtw0^d8j&aO5{-o+fRg> zejzctHgP@kMm%E&!VZdsVc9NkSz3?`r0-S*q%q;Hx!f;cyL8JDylRqyB04n8jT_8b zr(Fr&6PZ<_tcU>b5pt)!juc6usM>zG=z2I-JCEm=`4d5`?M&_p>)ho<*Rq1c@BM1dd5_GG)-apy}00D-;PYfZsa1s4Y zCji^GOFniY09#rJxzM?$Q5ni@T+15u#kGQqx2AD^&u>UC6d+Z@8VP5}^DU^r;uw_O zj`dM2jDtcVDuoy>D#GoyD@HlN;}^&nts|^UI=Ak_4=m0Dr=Fg9G1ME*E#B`Ow(L22 zMZ?Qaz$GrhU{~U-amyg!{ok^uzM$K@1|!Ws+kCchTRj3k(@c|}iRE$TsTBG}f6_Gs z1i}@-J01ZS;p?!}nOdPZmy6Bzbn#+3!@`b7`~y!osw|`pA|k)CrxqO7<+^-e%f)65 zn%wtg0m5Tgk$iJMl z=RR=yRI=f*^;QAxNA&WHb_jMOH>uGjG8zEUa&$k>v@0T8-OPjzjHImNC7u3@=m8+% znTuTbHN1DX5Tq;?M3vt7@ZpO6t^NL+&OBj`W1Fp2+9gc-D9#$K+pzTkm*q#ioI4=N z6hz+zv}wW4z?Z9O3+~zGWlyr7;)QBiUiWu>W5sM#p(1jBj8!vPtN1-wE9?<7iY(zT zLf=&=h`SmWe&i#ynq`~+w&_^7rG-s!*{xr94u>{55vqUhh_93b(21(D8Dhn5}Otrg9{15f&I*a)jAZY0S#!u9ZAvReMS zwD-6-G-TP#>DQkhcFNj3j;?)5LRS#jgws5Z=izu<*C~F-9HD+=kdpuXp^{?Mh4i;9 z57NUHGR5?iWCp?)tzC)ot~;=0_;F0NwhmpQ2Xq9!+(mtyZ7W-yjUDc&YgO#t@mgY@ z36wSc7B=|b*x+|Ti&f|R_M^~n^%mN~Veo1EMCwDDSj$Pghv0(fWau+=a9=~{scr-N zyqEo3G~x@#8y>J6tfIkf2f4y8eg5h$2I8IL5@N79h)f*Nl15`+YZBGxog!M`#AdnP zw<;w$Zbojvt<&1DCsxo{g0CA$kxm;?(Ga=(X$O0LXHJ;Ue?D|Ch{n?lp(e0{P6?ow zjq?jS`S_a4+{l*2l~5d1P*m4z<(NegdBg)>2X#jR~aIYDtg(+NHE zM>nlp8r}s7uLW;-dHOTXDPAC|ItCy_Xu=N#qoTrOHb0*&UWm_Vgv;J+7|lbnyA8>B zJppt~8XFrEsFZcwQc{L9i}iix*Oi|61JDxIX0BbPD{qU+LQ}(X68i)K+BG?kM1B8S zhLfg)lV&Z87{eyp+$hmJrS>=%N_-g*O}%?y3yI?}w|C(uu#`~%sn!=TX0^Q_=XAe+UtY(OP3_Oz$npReyOJsW z6ag8?7)K}_q3c(VzAqWihS@>xMe>U#B517UPU_Sd3eH}OWOCOr044_?^Kw5lVK5A4 zj})WYZUo@a`X4N0A8wON&ZGOyd&K%qe@`G^g{HEEc)&c{dTbx<9!Z9TgCZ);_q-fU zI2d$U`fk;zed*W8uR2RNV)G*zb6;}JFQvTjU{T`{j6i1bSSR|GG1ywEPA;6~Naepp zr3eY4%8Dvc9-Y2@tDXnKmB*<&GoBM;u8`-uLPKp^zqQ^aa1crm0Ja~1Lu~4e_8_$w z9WAh*&tT?M%L5P6Sl-@`^(lMCQs?@hTB!5$Lzl=1XCSrfF*0>GQ%LtV0&N$q$wqX0 zinw`(&>D_P$~$`E}rCzu=3%=@$q6fK=jX`xls$idMa zWjRINCGaO|(bvHo8X&;-rk6aVJoEa!AA_M`CBrPO#1YE}h+BZfamUb(LXAmzikJ;( z3Nf`Oc6DCF!By}P(W6h9uOHe~Sd8TX*`HKqjcCAP-DSDdK6bdj?q42P;nhPoF3+$b zx>{^;d(zD(w`{}<6VAIAsHmx_QR^|6K-U5$ZJDkKnnI|?7%wO7oVegF_U~U$$}!tA z>%au}UUzwb0oJXieB<-xBv8mQlj|r(nP<*BK7r18?&*uEw52I%WVfaa=QzO`PfYV02guu zRK-BUe|SiS5ELxvcOUVrV;fVX1x$%2WPmhv3Tvq(H8fAZOZ9zFo_?MDssw!(s5mCZ z?)o|;*IPj1j*!X-cM_rUUHFp$YgCA$o$_3|8NuOt%m`gnJz!ErO^merLixgz?g0wj zWbtwm72`hv#Z*dp^?_E7)ut-T);aJreb1HJRy|w^ZDgkV|4529Bb?x4qkDg4F0Hwp zYz4`c9Au-CLn*2^KLcd#MDv&?gBPTtLU6^J=y!9YMbN8{f&~h~0-YuS;mC(hGtuvZ zi112-R^JQa?@-c~C9r({z?1Gb{*Ma~%d;pjpM1!CWc@nJ&Vj*9WpnP{Xk55?CH)9l?XgTW+|0`V34 ziw0iKz9N~QzYL{m(pT}+CZn%sN(EgM7*I<;5>Fpfg`83`3TK&+i+!oPw=8@ZwGSrq zL@@(}i}vfE#U-$BldllPJg_e1S46nDd&&KcjwQj0Q3iKfwNYj5zkkqWS-AV~SuxTG zY4JfD@SqQv9V6dqemW=lx%6z)C{c|RMaBC9WKtovw-uMxoCh|#_apb^0}wVi`iM-U zc7K$TbSPzH?aUl|{y9R!^yIGGjii({R`Q! z?DB<2%qrDeUm?pXuZ>z8<^gBbAv_Eg^pkT?4TxRy8+-~z;t)*eS0Sg&t7n(3Af=Eo z#&n<^eH?B|Cu?H29;1r~wL3lJ1S86*p0~Y>COJ~CGIuJ~o#ne9MQnsu==SJ}bD7e` z$eG_a<%pJB4tu`6+^PqI()Ztgr@gl-F17qGC!g!|bg>(^E&vshxCF77vPm1yOrww2 zoQUyvAxgSUk?R|z_~Si~obxMGD!6J}qR=7kQ+Nz_k0zv~&eW;Rl*R#{oO1H~ zJo=kzR|d~~n^<1U^{@u7eS%JQvN%W=Um?&)E%XhX+1$-XBfiR#LBe-zxvu<2j(7ZI zqw1~UvlOxSg)XntkUM=QIx6{aIW4sm2R0nGW$5Yltxs7&+x(Vb*A}7ERT}i7Nf3YC z`ocjXeJb|etf=DLM?8E%GBS&X^hD0>q!EeT#IkJ#A%)ZIq+=Jc6d;l#J~Y5!x#BBs zyw(sd@|GPyVO1i;1E`}mh{*J@_a$O)-Z4pKmK}zxSZGKjfpgh%a8s9Bk!kjWYm?HH z1YeDgc-SHoeA}cVwS?;@CSnX$W^61y*Riz5NQZra*d}%8d1KU?erPs?@;$IhJKisk z3AwK2sS-gFuL*28IAJmZ{#)@E$uAt(X)el*w_s7$P~Wa#4XB*HS3cKq zM933;8`h%9#ICmcH%V$q3<>Jvyl%d@CH@G|&=Z0H!qv@|-69Xor_AN+(u?ZY3;y7i zm4GoD1-`4%nd1skaY^zFY>gv$MCd<_~<#47|yarcOOY z{W<;M5x*fsj_K{m*GXzIj1KD+hnEa4eEGkQzQ^ z=T-_j_BN-f3))qO&ilD%wxF6uvdn;FQvhjN*ae2&7ml%eiyO8IEJFQ)6PjA&=ngEq zmSvc#{6i%0OMJP+4>6BzD8?Ze|UXtSl{iTxcv5$A$S&g;i>@98y47(%Q=J}uh z-khO?v?`LBbaeep6hI*5JPlV7;U!@Eyz z96&gQ#+A(hv`{y0W-bA!T{1V#`1G?;2ufy`v*G`BAc27ve36J`v`bw&pyJ^V-y|PJyXX2KyF#osr_24JZbZTq758_!SYIDP1<^{i>f;vEr-V@{*bq z5x?!dV_I6+a0oo{<6RyB#?}l%+6Ex8^c;?Ip~U>H@@h*{2QFjnAx`g&$vcqAC^_s8 zuS234N{Q3P;#VQ2M9AlmWG;GBG!b>AdMCCIu3Z^pP}a=KKRF@avJRGt?sqUT zz63dAHp)@pjG=o7dM=?q?_NqlqTksI#tRP_A?PGeopQiv{(U;YBYY9ZN)Tnr#CT&g zLg2~f-V04J8o65l$6XomQG>EpU(GD0H`D7LGnYK?BAZnHhDBeVE;eWl2ZL@?ay)ZA z>@a8(jSUpnd_`J`=$#O_pCE`MJ@ZQ`r3ce{*{^-xIBV zGL6`mgVsJGE(v5+hq-hIudm)xVeZrgiJ^@$TMnv3X1U&DZWWk90mK;bRmt6TE5W;i zGt;D%NJSbc7ACnZ+}_)mdbX5@Y`0@*7z_gM0?S7yj;$%+W^RehGNd=dE>Wkx!e25b zS0C3RCWU+82yMCYA?vOe1{P%YFb6GCuywt?J{O1IB{C$+_-b)^VWWu>VnMS7M1OK0!LY0L>wHI`~4qSB`tzc^7?~QOLTk|xM#c&Wv zics!+1CrM9n|<+ZcB!^xy#)IUr<2iz9%^3RcxE6PjkS|0IhuV7I_oZ9xhK5hJMq+y zB<9sJm0yP!OH7RuOl&%ug`@C(@FLb|R0T1gSktD8&u*>=Ot&&WM zbvoD6OiWV7Wne@F=G$GGG`3Bipj=U&p$i(6)v^l`{6ybJXNjV*T{-iA#Hnz=smQIA zBY6@rQ;p0h%D-W#m>H)_b3y(2LP&P5ni}9lCwGEDZ;K{qXN^~NE(_f!bl{lVf~++U zVlp^YG5uYu(b)<&(9m$#%S5BtBj3XwZzCGT`cvq(C1)o-FMRdc%tT`=19V?*cv+3( z-+leF<0dQ$Y4;)IAn5fwu#NIafL+h4Qa*OQ9(i+0Md~ z%=bLlI#8Yl3q?wCgrIIonmlJ*1 z=5F8)o)v32@r|bOZ>V^}t6-wlV*2OeH=khtA2BnD zkYghpYNGVPKVNm-OcVUP$9{w(cX}E}=vvCJ=JR^lhq{M3y-9u{cn!mfv~?XgUuf1n zk`rx9G#xeLy$C+%Vq6+R(`ohXnWsqGqbaGfV!1ShJ^}!|x*FX)=1eQJx@`eJn$Zd# zcMRaS4jkffq9MaU{ghxz%M6WTCk9Lp98#0%UqMUm^6##Wbu>etxO>4NMezVN;{BSQ zq7xp(YXh)AV20wMo0YwKlGm?WXDKn{p{Q=tx}F|n8apv^pce6iI?+`{v47dFC`$M0`g_`XsaHi&k00xbJK#4E=bRqE{qdSH#Tvy+HfB$3#jfv?D^q z^%@HI7Oj_vz2BSkdSGFD?ID7Uicl%MoQEj1kSQ3deXAmV1L}aVVmaD=aY7TAHVDt9 z;`sezO|$(TF+v_Tyi9r~AMEUYUY@8+pxm<_~%Z=IKDiz(u&&F6tAJ#>(x z9WX66Jvr%tUcu+AZ@THCyLll~33J7=M>vs>V@^epA6YxTezF!E;~{E58PlJBG^eQ*;X_U=wm%g%f$I2zKpsBzI*_{dZNB_9wRSd(r>KV;IvdVbgFG$YR&CocBV-Slth z{Or(-Ef0Dx;Ep@j)K8dFa_M9%^}_kV_3mR{`{Ew!&GnwB=wkPwTUC|-I~KfxDl+8+ zMN(g%HJSsp+G|^yX-d~h*Ak|L1@+y^`-X(`)UhE32Zs!B0&Q~K=-=o;)@i5ep3@&Q zx^9pukC*8_bVeshCVTA$)Ol&3w`zWM(1r}c5?On1KHOfXNONf|>nPeSSgpJ4z!(dB z6HM&OmbV0b8G5O2icwJr{uE(9@|u50nbGTZ``!~@5fKj%+otn@m9Ka11qvh|K^2S` zirQ!Kt?ClDMooXUL8LD8SU1c%TjH>^114YuHp-8!F30p3kIZxx;qPPQu(R!k2Rw?<0>kj9Vk?d!*O3%4|xdbZOF+Q>|p&Ua*wW z2(k=xzlNs*&=Si*zH)8yx~lzmElSw@yGzfI9wZj!H24f4KIl-jHyfC%V}+<2sqI+l zmuVnZy#0Obi+ZLbAd)l%D)F&t!WNUR8>l4 zUUR@-=OjGCPOjZTi%TG{N325A`nK*3%S+!|zOedDPjB(*)bfS?t-P1;`z=|_P7x3E zw^RTPqRB(<-+;4Erdw_YIrMYF^5Z#Ow?Cd9gG<3Q#=$@8u)1!TYC2FtF6AMfF>WUsE3>00~M2NrC z`Z|#*S+vJ`X97JmXP!4JuCu3VO&L?{ko7U=yH#o7J!8@7H$F(sEF?^-`@U?A4IRqY zuKq;1BpHZxY@ zmW@YE0!Mz-7p(X4r|T^a#1u(ktNxwUDP7wYZTdO6MGJpt1=zgnHbG4A#Ul48`}e!B zgKj+UZ>?`)tOD{T{I(hYX_Jl!I@#iADJOS|Skc4FtZvNiAd!5@T3a(VE zv1%LnjBR75dY4uguW6Z0zwx&0SQQ{Cn#AxS*>Z!Nif@-C^Ja8+_%4p48}$PN31_yZ zob)&+lUc#6FH!EgSpigFp7#=aEV^8O{PeV-&0OWRojcnUDyL`rc*VRrx``AO)S*2! z-4VJJE6RMHVZdo>z%e>`q}TuDmypE6<1V(Lp}C61T(s)4>U-n-3;y`Uy`lm`V#I@v zguYDm^FLc-1tY}g?$`gb+~v1h)K2|z{@oMP2HWSRk~eh@%Xoeb3z9j@@t6EEe&~A^ zVTZ$I+huD%-in@#oBy9?`_3I3HjF1-os8I+UgUntdMy)I09yh*qTa~JNX!2#x4m)O z@7lV?6#vRc(IfxXUagy{vufO=qCI|j&CxKGn5c<*45!5zojVitcc6*J2AYE>^;Azt zjH&H@ksnXAs`tFnb-)i7ZYZg-e>C*-Sw~aVUxXLUh*|{4fqScycY0b}#@)>fRvQ*? z*ST`W&GhTQ?l~ipu@mm?7f)b@JKP*{^B1C`Cm9l);F)yIgxN1s{VpF$J^d967ME~P z%f__g?Ir@ibY5sX6*eC)kvKQ~DzM>X>|wRt*M5&Mw7bf(tU3p$I%T==j{9xMnk6d- zLJpZ)wNe$|dr(s$9Vtn*`qoq4_gr#&f;N5hziqa(Ox5ixMpIoz-_5pbLX|+)&gI>uLT9F2 zJ}Czoa_$aSRp7Kr)hOChiwUo~qzvCPqARu%|dc50}ZfOUMWX=W6l~Ald-1q%lQtDSfd3GTum1lW? z%I9DW0A{3?O9(K11%6h9a*d5xO&-Hfu(mNKzufvgfsCnKcL0+|q7E=enZ0{;Zq184j=xab#mRXwc4jQ_&Q)%nmEz-EC~Wu_4Wg29JO9%5lgN@?R870*;Z=}>)`o;u$(Q?*Mm$w_+gwr&Gyl4(2J zB99K#gl(Cfy!lS#&I_Xv4u1{netPpXct{tG&NKcq!8ThO@u!c{1KV=;dQ= z)xm%4x!;DaUO%SddgZe3by%I&X*27aztXEA|FHZ6*Arp|!Y>TlY5bPKtC#d)7yslK&3a(J_FPJds3pmDj z{PBLO(MxTU*YaV>`1_uWiIZn`I{a4OdsnaR)QIR;LE?RRj&tQ1h0i9xr~GI({d1eI zYNZ|PP10ZFakO_3ri>(z^;<5{btmtz++rp|5=mC&&M;$r_Tpb0M|J;T2Ta(hmS2TOmb?5cjVHR<3Z=v zE`C8?MNjkL*(9>Jzd(Eaos$C#928LyW_abZsFKdJR=K_zTHDygfdIsBS^b$4nK!Pv zTQiLAz8@C7LtOi@hB|R)bzVP_5JReYyz z>ohJUi@P0#r5}#}x#i$&f3BEc_Pb$``%jDeiMX#_o%mf(u*Mig*;tddX%|KGU|sx= zn@d~1Qf*onUuVz#R}-}=`Z*)qX0BJWKhy@ac?e|SGSbHkuTAUT?HsDZMn7Nb)<(N! z@=iU~Ns9Dyp}V}gC8u#uY+w4gcbK2@s+G6@F^sz_5bc{BEA@BUddkIr_PV#EM`ff| z@a^A{B}*5VI;e{zAxdW~&hN-SrER98CnCQK4(1F695;=)+m`0(QthoGY^wIUxp`c} zMSZ+;{(Fel72of{KQ#wXqa$tm`eD7=Qm@xcN|?&x-Z*@}YIFAvHz_}XU$6a@+Cvn( z4*dE5!LR>IpopQTWMO3&&ke(}OL|tf{kr^MK3IM%F!ri;~3m zl0_7cF~{h2d-bxn1V;6ZnQ8tqSbT4x&F^ojI=2GcG8bHUcV$MkRbAlYCYP-}*<7piCWw-RzvtVQxpQ7q&GH5kx(Q&G6iy%V(of$Vr$TAC)U3eY z@BZ0!pK?c##w)`=^P8RD{!MJ>zj;~94j*i8dMsj_%rOeu`e*$6A867%Vr=lkydjx| z=1+DU5%H9%|KzYZUE;c97b@enPmN1xil`Y}DwCRq@O{d6M?MKlExxPkD=XVN>S*H+ zgF%_Zx;t8>+DDq7R}^s3R?&#PaoA#Sj&=y5eITkrQHrhjH3 z`PmOM+l`fP+1It!t2JmZPRoi$cK2(sFe~b~evp*kP1Dmudrv+t%vEKtAI@KZ5*Qzo zzi+9Bl>Ih!3QaAqmL7_435?t=UMP4lYb1S>o3*Nl8f)y&bw`d)PPVhv3pjzaUg>NJ zzgv5sw0l!U`EUDb&3H|G#uv9O+Fl*!GjVVEHaV; Date: Fri, 21 Jun 2019 23:18:15 +1000 Subject: [PATCH 08/17] Remove duplicate computation --- src/lines.jl | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index 70d7fe1..cd62ce5 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -93,7 +93,7 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end @@ -114,7 +114,7 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end @@ -134,7 +134,7 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) end return vcat.(curves...) end @@ -152,7 +152,7 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, outangle) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) end return vcat.(curves...) end @@ -166,22 +166,16 @@ function arrowcoords(θ, endx, endy, arrowlength, angleoffset=20.0/180.0*π) return (arr1x, arr1y), (arr2x, arr2y) end -function curveedge(x1, y1, x2, y2, θ) - Δx = x2 - x1 - Δy = y2 - y1 +function curveedge(x1, y1, x2, y2, θ, outangle, d; k=0.5) - θ1 = atan(Δy,Δx) - - d = sqrt(Δx^2 + Δy^2) - - r = d/2 + r = d * k # Control points for left bending curve. - xc1 = x1 + r * cos(θ1 + θ) - yc1 = y1 + r * sin(θ1 + θ) + xc1 = x1 + r * cos(θ + outangle) + yc1 = y1 + r * sin(θ + outangle) - xc2 = x2 + r * cos(θ1 + π - θ) - yc2 = y2 + r * sin(θ1 + π - θ) + xc2 = x2 + r * cos(θ + π - outangle) + yc2 = y2 + r * sin(θ + π - outangle) return [(x1,y1), (xc1, yc1), (xc2, yc2), (x2, y2)] end From 9df0e27cec1ac80e1d5a16e106fb09d70d1784bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Fri, 21 Jun 2019 23:33:39 +1000 Subject: [PATCH 09/17] Preserve style Revert to less aggressive control points. --- src/lines.jl | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index cd62ce5..f4003e8 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -87,13 +87,17 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + # d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ+outangle) starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + + d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) + arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end @@ -108,13 +112,17 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + # d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ+outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + + d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) + arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end @@ -128,13 +136,16 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + # d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ+outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + + d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) end return vcat.(curves...) end @@ -146,13 +157,16 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + # d = sqrt(Δx^2 + Δy^2) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ+outangle) starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + + d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) end return vcat.(curves...) end From a96c663b8e5fababf3a33f0b7ff7206c6fe95867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Sat, 22 Jun 2019 00:16:33 +1000 Subject: [PATCH 10/17] Basic implementation of self directed loops --- src/lines.jl | 16 ++++++++++++++++ test/data/self_directed.png | Bin 0 -> 36946 bytes test/runtests.jl | 10 ++++++++++ 3 files changed, 26 insertions(+) create mode 100644 test/data/self_directed.png diff --git a/src/lines.jl b/src/lines.jl index f4003e8..b49abc2 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -96,6 +96,10 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + if i == j + d2 = 2 * π * nodesize[i] + end + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) @@ -121,6 +125,10 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + if i == j + d2 = 2 * π * nodesize + end + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) @@ -145,6 +153,10 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + if i == j + d2 = 2 * π * nodesize + end + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) end return vcat.(curves...) @@ -166,6 +178,10 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + if i == j + d2 = 2 * π * nodesize[i] + end + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) end return vcat.(curves...) diff --git a/test/data/self_directed.png b/test/data/self_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..1eb117704e79b5c9c7fffb5a55095b53de58143a GIT binary patch literal 36946 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

iTlhrhbg4+z8C>WH5R5 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 success + + g3 = DiGraph(2) + add_edge!(g3, 1,1) + add_edge!(g3, 1,2) + add_edge!(g3, 2,1) + + plot_and_save2(fname) = plot_and_save(fname, g3, linetype="curve") + refimg2 = joinpath(datadir, "self_directed.png") + @test test_images(VisualTest(plot_and_save2, refimg2), popup=!istravis) |> success + end From c1d5ef9bcfe6119415a314586bc53bc8f747778e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Sat, 22 Jun 2019 13:53:50 +1000 Subject: [PATCH 11/17] Save comparisons --- .gitignore | 1 + test/runtests.jl | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index ccb1692..de8079e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.jl.mem *.svg Manifest.toml +test/data/*-comparison.png diff --git a/test/runtests.jl b/test/runtests.jl index 3f5fa62..176f5ec 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -10,6 +10,7 @@ using Compose using Random using Test using VisualRegressionTests +using ImageMagick # global variables istravis = "TRAVIS" ∈ keys(ENV) @@ -42,6 +43,13 @@ function plot_and_save(fname, g; gplot_kwargs...) draw(PNG(fname, 8inch, 8inch), gplot(g; layout=test_layout, gplot_kwargs...)) end +function save_comparison(result::VisualTestResult) + grid = hcat(result.refImage, result.testImage) + path = joinpath(datadir, string(basename(result.refFilename)[1:end-length(".png")], "-comparison.png")) + ImageMagick.save(path, grid) + return result +end + @testset "Karate Net" begin # auxiliary variables nodelabel = collect(1:nv(g)) @@ -50,12 +58,12 @@ end # test nodesize plot_and_save1(fname) = plot_and_save(fname, g, nodesize=nodesize.^0.3, nodelabel=nodelabel, nodelabelsize=nodesize.^0.3) refimg1 = joinpath(datadir, "karate_different_nodesize.png") - @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> success + @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> save_comparison |> success # test directed graph plot_and_save2(fname) = plot_and_save(fname, g, arrowlengthfrac=0.02, nodelabel=nodelabel) refimg2 = joinpath(datadir, "karate_straight_directed.png") - @test test_images(VisualTest(plot_and_save2, refimg2), popup=!istravis) |> success + @test test_images(VisualTest(plot_and_save2, refimg2), popup=!istravis) |> save_comparison |> success # test node membership membership = [1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,2,1,1,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2] @@ -63,14 +71,14 @@ end nodefillc = nodecolor[membership] plot_and_save3(fname) = plot_and_save(fname, g, nodelabel=nodelabel, nodefillc=nodefillc) refimg3 = joinpath(datadir, "karate_groups.png") - @test test_images(VisualTest(plot_and_save3, refimg3), popup=!istravis) |> success + @test test_images(VisualTest(plot_and_save3, refimg3), popup=!istravis) |> save_comparison |> success end @testset "WheelGraph" begin # default options plot_and_save1(fname) = plot_and_save(fname, h) refimg1 = joinpath(datadir, "wheel10.png") - @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> success + @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> save_comparison |> success end @testset "Curves" begin @@ -81,7 +89,7 @@ end plot_and_save1(fname) = plot_and_save(fname, g2, linetype="curve") refimg1 = joinpath(datadir, "curve.png") - @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> success + @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> save_comparison |> success g3 = DiGraph(2) add_edge!(g3, 1,1) @@ -90,6 +98,6 @@ end plot_and_save2(fname) = plot_and_save(fname, g3, linetype="curve") refimg2 = joinpath(datadir, "self_directed.png") - @test test_images(VisualTest(plot_and_save2, refimg2), popup=!istravis) |> success + @test test_images(VisualTest(plot_and_save2, refimg2), popup=!istravis) |> save_comparison |> success end From 480f568b9e13a38e5a7483dea7ac915d690af98f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Mon, 24 Jun 2019 09:59:52 +1000 Subject: [PATCH 12/17] Use safer hypot function --- src/lines.jl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index b49abc2..0ca22d7 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -9,7 +9,7 @@ function graphline(g, locs_x, locs_y, nodesize::Vector{T}, arrowlength, angleoff j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) @@ -30,7 +30,7 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real, arrowlen j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) @@ -50,7 +50,7 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real} j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) @@ -68,7 +68,7 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = sqrt(Δx^2 + Δy^2) + d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) @@ -87,14 +87,14 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = sqrt(Δx^2 + Δy^2) + # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ+outangle) starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + d2 = hypot(endx-startx, endy-starty) if i == j d2 = 2 * π * nodesize[i] @@ -116,14 +116,14 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = sqrt(Δx^2 + Δy^2) + # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ+outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + d2 = hypot(endx-startx, endy-starty) if i == j d2 = 2 * π * nodesize @@ -144,14 +144,14 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = sqrt(Δx^2 + Δy^2) + # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ+outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + d2 = hypot(endx-startx, endy-starty) if i == j d2 = 2 * π * nodesize @@ -169,14 +169,14 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = sqrt(Δx^2 + Δy^2) + # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ+outangle) starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - d2 = sqrt((endx-startx)^2 + (endy-starty)^2) + d2 = hypot(endx-startx, endy-starty) if i == j d2 = 2 * π * nodesize[i] From 886945e5a4cb1575cb10d6af5473b04af2912406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Mon, 24 Jun 2019 10:04:08 +1000 Subject: [PATCH 13/17] Remove unused distance calculations --- src/lines.jl | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index 0ca22d7..100497f 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -9,7 +9,6 @@ function graphline(g, locs_x, locs_y, nodesize::Vector{T}, arrowlength, angleoff j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) @@ -30,7 +29,6 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real, arrowlen j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) @@ -50,7 +48,6 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real} j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ) starty = locs_y[i] + nodesize[i]*sin(θ) @@ -68,7 +65,6 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ) starty = locs_y[i] + nodesize*sin(θ) @@ -87,20 +83,19 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ+outangle) starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - d2 = hypot(endx-startx, endy-starty) + d = hypot(endx-startx, endy-starty) if i == j - d2 = 2 * π * nodesize[i] + d = 2 * π * nodesize[i] end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -116,20 +111,19 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ+outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - d2 = hypot(endx-startx, endy-starty) + d = hypot(endx-startx, endy-starty) if i == j - d2 = 2 * π * nodesize + d = 2 * π * nodesize end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] @@ -144,20 +138,19 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize*cos(θ+outangle) starty = locs_y[i] + nodesize*sin(θ+outangle) endx = locs_x[j] + nodesize*cos(θ+π-outangle) endy = locs_y[j] + nodesize*sin(θ+π-outangle) - d2 = hypot(endx-startx, endy-starty) + d = hypot(endx-startx, endy-starty) if i == j - d2 = 2 * π * nodesize + d = 2 * π * nodesize end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) end return vcat.(curves...) end @@ -169,20 +162,19 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real j = dst(e) Δx = locs_x[j] - locs_x[i] Δy = locs_y[j] - locs_y[i] - # d = hypot(Δx, Δy) θ = atan(Δy,Δx) startx = locs_x[i] + nodesize[i]*cos(θ+outangle) starty = locs_y[i] + nodesize[i]*sin(θ+outangle) endx = locs_x[j] + nodesize[j]*cos(θ+π-outangle) endy = locs_y[j] + nodesize[j]*sin(θ+π-outangle) - d2 = hypot(endx-startx, endy-starty) + d = hypot(endx-startx, endy-starty) if i == j - d2 = 2 * π * nodesize[i] + d = 2 * π * nodesize[i] end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d2) + curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) end return vcat.(curves...) end From 31a69e3520af4f358e75ab3c969dffe311df32bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Mon, 24 Jun 2019 14:18:36 +1000 Subject: [PATCH 14/17] Update Project.toml compat section --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index f199533..0a99095 100644 --- a/Project.toml +++ b/Project.toml @@ -24,6 +24,6 @@ VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" test = ["Test", "Cairo", "ImageMagick", "VisualRegressionTests"] [compat] -"Compose" = "0.7" -"LightGraphs" = "1.1" -"VisualRegressionTests" = "0.2" +"Compose" = "~0.7" +"LightGraphs" = "~1" +"VisualRegressionTests" = "~0.3" From 972d7fad2ea365b6c02c766c1ac56cc698667baa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Mon, 24 Jun 2019 14:41:22 +1000 Subject: [PATCH 15/17] Update curve type --- src/lines.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index 100497f..87dd85e 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -76,7 +76,7 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T end function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, arrowlength, angleoffset, outangle=pi/5) where {T<:Integer} - curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) + curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) arrows = Array{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) @@ -104,7 +104,7 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real end function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, outangle=pi/5) - curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) + curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) arrows = Array{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) @@ -132,7 +132,7 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, end function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) - curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) + curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) j = dst(e) @@ -156,7 +156,7 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) end function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, outangle) where {T<:Integer} - curves = Array{Vector{Tuple{Real,Real}}}(undef, ne(g)) + curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) j = dst(e) From d85cb80a2cdb241b8096ff1641063018b3957292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Tue, 25 Jun 2019 17:16:46 +1000 Subject: [PATCH 16/17] Try more liberal Compat requirement --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 0a99095..4787256 100644 --- a/Project.toml +++ b/Project.toml @@ -26,4 +26,4 @@ test = ["Test", "Cairo", "ImageMagick", "VisualRegressionTests"] [compat] "Compose" = "~0.7" "LightGraphs" = "~1" -"VisualRegressionTests" = "~0.3" +"VisualRegressionTests" = "~0.2, ~0.3" From 92dcc352c834578ff818b6c8721d9f2839dfdd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Wed, 26 Jun 2019 20:09:27 +1000 Subject: [PATCH 17/17] Remove splats and slurps --- src/lines.jl | 26 +++++++++++++------------- src/plot.jl | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lines.jl b/src/lines.jl index 87dd85e..4589641 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -76,7 +76,7 @@ function graphline(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Real) where {T end function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, arrowlength, angleoffset, outangle=pi/5) where {T<:Integer} - curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) + curves = Matrix{Tuple{Float64,Float64}}(undef, ne(g), 4) arrows = Array{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) @@ -95,16 +95,16 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real d = 2 * π * nodesize[i] end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + curves[e_idx, :] = curveedge(startx, starty, endx, endy, θ, outangle, d) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end - return vcat.(curves...), arrows + return curves, arrows end function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, outangle=pi/5) - curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) + curves = Matrix{Tuple{Float64,Float64}}(undef, ne(g), 4) arrows = Array{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) for (e_idx, e) in enumerate(edges(g)) i = src(e) @@ -123,16 +123,16 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, d = 2 * π * nodesize end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + curves[e_idx, :] = curveedge(startx, starty, endx, endy, θ, outangle, d) arr1, arr2 = arrowcoords(θ-outangle, endx, endy, arrowlength, angleoffset) arrows[e_idx] = [arr1, (endx, endy), arr2] end - return vcat.(curves...), arrows + return curves, arrows end function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) - curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) + curves = Matrix{Tuple{Float64,Float64}}(undef, ne(g), 4) for (e_idx, e) in enumerate(edges(g)) i = src(e) j = dst(e) @@ -150,13 +150,13 @@ function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle) d = 2 * π * nodesize end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + curves[e_idx, :] = curveedge(startx, starty, endx, endy, θ, outangle, d) end - return vcat.(curves...) + return curves end function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, outangle) where {T<:Integer} - curves = Vector{Vector{Tuple{Float64,Float64}}}(undef, ne(g)) + curves = Matrix{Tuple{Float64,Float64}}(undef, ne(g), 4) for (e_idx, e) in enumerate(edges(g)) i = src(e) j = dst(e) @@ -174,9 +174,9 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real d = 2 * π * nodesize[i] end - curves[e_idx] = curveedge(startx, starty, endx, endy, θ, outangle, d) + curves[e_idx, :] = curveedge(startx, starty, endx, endy, θ, outangle, d) end - return vcat.(curves...) + return curves end # this function is copy from [IainNZ](https://github.com/IainNZ)'s [GraphLayout.jl](https://github.com/IainNZ/GraphLayout.jl) @@ -199,5 +199,5 @@ function curveedge(x1, y1, x2, y2, θ, outangle, d; k=0.5) xc2 = x2 + r * cos(θ + π - outangle) yc2 = y2 + r * sin(θ + π - outangle) - return [(x1,y1), (xc1, yc1), (xc2, yc2), (x2, y2)] + return [(x1,y1) (xc1, yc1) (xc2, yc2) (x2, y2)] end diff --git a/src/plot.jl b/src/plot.jl index e6cddcb..73b34a8 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -196,11 +196,11 @@ function gplot(g::AbstractGraph{T}, if linetype == "curve" if arrowlengthfrac > 0.0 curves_cord, arrows_cord = graphcurve(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle) - lines = curve(curves_cord...) + lines = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4]) arrows = line(arrows_cord) else curves_cord = graphcurve(g, locs_x, locs_y, nodesize, outangle) - lines = curve(curves_cord...) + lines = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4]) end else if arrowlengthfrac > 0.0