Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.jl.mem
*.svg
Manifest.toml
test/data/*-comparison.png
180 changes: 86 additions & 94 deletions src/lines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ 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)
θ = 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]*cos(θ)
endy = locs_y[j] + nodesize[j]*sin(θ)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for adding Pi here? Isn't it the case, that cos(x + π) == -cos(x) and sin(x + π) == -sin(x) ?

Copy link
Contributor Author

@CiaranOMara CiaranOMara Jun 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it the case, that cos(x + π) == -cos(x) and sin(x + π) == -sin(x) ?

Yes, this is true.

julia> using Test
julia> for θ in 0:45:360
       @test sind(θ+180) == -sind(θ)
       @test cosd(θ+180) == -cosd(θ)
       end

What is the reason for adding Pi here?

The reason I added pi here is so that the structure of the code is concordant with how I was thinking about the problem. I framed the problem as being at the jth point, looking back at the ith point (theta+pi), then moving from the jth point toward the ith point (+cos, +sin).

lines[e_idx] = [(startx, starty), (endx, endy)]
arr1, arr2 = arrowcoords(θ, endx, endy, arrowlength, angleoffset)
arrows[e_idx] = [arr1, (endx, endy), arr2]
Expand All @@ -30,12 +29,11 @@ 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)
θ = 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*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]
Expand All @@ -50,12 +48,11 @@ 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)
θ = 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]*cos(θ)
endy = locs_y[j] + nodesize[j]*sin(θ)
lines[e_idx] = [(startx, starty), (endx, endy)]
end
lines
Expand All @@ -68,103 +65,118 @@ 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)
θ = 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*cos(θ)
endy = locs_y[j] + nodesize*sin(θ)
lines[e_idx] = [(startx, starty), (endx, endy)]
end
return lines
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 = 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)
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)
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(θ)
lines[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]
θ = 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)

d = hypot(endx-startx, endy-starty)

if i == j
d = 2 * π * nodesize[i]
end

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 lines, arrows
return curves, arrows
end

function graphcurve(g, locs_x, locs_y, nodesize::Real, arrowlength, angleoffset, outangle=pi/5)
lines = Array{Vector}(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)
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)
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(θ)
lines[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]
θ = 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)

d = hypot(endx-startx, endy-starty)

if i == j
d = 2 * π * nodesize
end

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 lines, arrows
return curves, arrows
end

function graphcurve(g, locs_x, locs_y, nodesize::Real, outangle)
lines = Array{Vector}(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)
Δx = locs_x[j] - locs_x[i]
Δ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(θ)
lines[e_idx] = curveedge(startx, starty, endx, endy, outangle)
θ = 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)

d = hypot(endx-startx, endy-starty)

if i == j
d = 2 * π * nodesize
end

curves[e_idx, :] = curveedge(startx, starty, endx, endy, θ, outangle, d)
end
lines
return curves
end

function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real}, outangle) where {T<:Integer}
lines = Array{Vector}(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)
Δx = locs_x[j] - locs_x[i]
Δ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(θ)
lines[e_idx] = curveedge(startx, starty, endx, endy, outangle)
θ = 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)

d = hypot(endx-startx, endy-starty)

if i == j
d = 2 * π * nodesize[i]
end

curves[e_idx, :] = curveedge(startx, starty, endx, endy, θ, outangle, d)
end
return lines
return curves
end

# this function is copy from [IainNZ](https://github.com/IainNZ)'s [GraphLayout.jl](https://github.com/IainNZ/GraphLayout.jl)
Expand All @@ -176,36 +188,16 @@ 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
function curveedge(x1, y1, x2, y2, θ, outangle, d; k=0.5)

# 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
r = d * k

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]
# Control points for left bending curve.
xc1 = x1 + r * cos(θ + outangle)
yc1 = y1 + r * sin(θ + outangle)

xc2 = x2 + r * cos(θ + π - outangle)
yc2 = y2 + r * sin(θ + π - outangle)

return [(x1,y1) (xc1, yc1) (xc2, yc2) (x2, y2)]
end
8 changes: 4 additions & 4 deletions src/plot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4])
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[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4])
end
else
if arrowlengthfrac > 0.0
Expand Down
Binary file added test/data/curve.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/data/self_directed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 33 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ using Compose
using Random
using Test
using VisualRegressionTests
using ImageMagick

# global variables
istravis = "TRAVIS" ∈ keys(ENV)
Expand Down Expand Up @@ -48,6 +49,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))
Expand All @@ -56,25 +64,46 @@ 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]
nodecolor = [colorant"lightseagreen", colorant"orange"]
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

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) |> save_comparison |> 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) |> save_comparison |> success

end