如何用 Julia 语言绘制圆形扇区?
How to draw a circular sector in the Julia language?
我是 Julia 语言的新手,需要在图像上绘制一个圆形扇区(灰色版本的 2 维 UInt8 数组或 RGB 版本的 3 维 UInt8 数组)。之后该图像将用作其他数组中 select 数据的掩码,因此我需要结果,而不是作为图像对象,而是作为布尔值或整数数组。
有ImageDraw包画圆的方法:
draw!(img, Ellipse(CirclePointRadius(350,200,100), fill = tue))
但找不到提供开始和结束角度的方法。
您可以使用 Luxor.jl's pie
or sector
function:
julia> begin
img = readpng("/path/Images/deepam.png")
Drawing(img.width, img.height, "sector-on-img.png")
placeimage(img)
origin()
sethue("orange")
pie(0, 0, 100, π/2, π, :fill)
sethue("olive")
sector(25, 125, 3π/2, 0, 15, :fill)
finish()
end
true
结果:
(原始png图像缩小,用于比较:
)
我认为 Julia 是一种很棒的语言,因为(除其他外)所有库都是用相同的语言实现的,而且您可以轻松访问它们的源代码。
并且通过这种方式,我已经能够修改 ImageDraw 库的 ellipse2d.jl 脚本。
修改的内容是再添加一个draw的定义!接受开始和结束角度的椭圆对象的函数(Julia 的多次分派也很棒)。
我认为最好的方法是定义新对象 ellipse_sector 和 circle_sector,它们与椭圆和圆形对象相同,但多了两个成员:start_angle 和 end_angle。然后应该实现相应的绘图功能。我想写信给 ImageDraw
包开发人员以提出这个建议,甚至让我进行这些更改,但我不知道 github.
的管理
相反,我的解决方案不修改任何现有对象,只是添加一个绘制方法!接受另外两个参数的函数:startAngle 和 endAngle。
这是要复制到 ellipse2d.jl 脚本末尾的代码:
function draw!(img::AbstractArray{T, 2}, ellipse::Ellipse, startAng::Real, endAng::Real, color::T) where T<:Colorant
# Solution to find out if an angle lies between two given ones, borrowed from:
#
# Make all angles to lie in [0, 2π)
# rem2pi(ϕ, RoundNearest) returns the remainder of the division by 2π in the range [−π,π]
# mod2pi returns the remainder of the division by 2π in the range [0,2π)
Angle1 = mod2pi(startAng)
Angle2 = mod2pi(endAng)
# make the angle from angle1 to angle2 to be <= 180 degrees
rAngle = mod2pi( mod2pi(Angle2 - Angle1) + 2π)
if rAngle >= π
Angle1, Angle2 = Angle2, Angle1 # Swaps the values
end # if
ys = Int[]
xs = Int[]
break_point = 0
if ellipse.fill == false
break_point = ((ellipse.ρy - ellipse.thickness) / ellipse.ρy) ^ 2 + ((ellipse.ρx - ellipse.thickness) / ellipse.ρx) ^ 2
end
for i in ellipse.center.y - ellipse.ρy : ellipse.center.y + ellipse.ρy
for j in ellipse.center.x - ellipse.ρx: ellipse.center.x + ellipse.ρx
y = i - ellipse.center.y
x = j - ellipse.center.x
val = (x / ellipse.ρy) ^ 2 + (y / ellipse.ρx) ^ 2
# atan(y, x) returns the angle in the correct quadrant [−π,π], not like atan(y/x)
# But make it to be in the range [0, 2π)by means of mod2pi()
ang = mod2pi( atan(y, x) )
# Test if the angle lies betwen the startAngle and the endAngle
if (Angle1 <= Angle2)
AngleIsBetween = ang >= Angle1 && ang <= Angle2
else
AngleIsBetween = ang >= Angle1 || ang <= Angle2
end # if
if val < 1 && val >= break_point && AngleIsBetween
push!(ys, i)
push!(xs, j)
end
end
end
for (yi, xi) in zip(ys, xs)
drawifinbounds!(img, yi, xi, color)
end
img
end
我是 Julia 语言的新手,需要在图像上绘制一个圆形扇区(灰色版本的 2 维 UInt8 数组或 RGB 版本的 3 维 UInt8 数组)。之后该图像将用作其他数组中 select 数据的掩码,因此我需要结果,而不是作为图像对象,而是作为布尔值或整数数组。
有ImageDraw包画圆的方法:
draw!(img, Ellipse(CirclePointRadius(350,200,100), fill = tue))
但找不到提供开始和结束角度的方法。
您可以使用 Luxor.jl's pie
or sector
function:
julia> begin
img = readpng("/path/Images/deepam.png")
Drawing(img.width, img.height, "sector-on-img.png")
placeimage(img)
origin()
sethue("orange")
pie(0, 0, 100, π/2, π, :fill)
sethue("olive")
sector(25, 125, 3π/2, 0, 15, :fill)
finish()
end
true
结果:
(原始png图像缩小,用于比较:
我认为 Julia 是一种很棒的语言,因为(除其他外)所有库都是用相同的语言实现的,而且您可以轻松访问它们的源代码。
并且通过这种方式,我已经能够修改 ImageDraw 库的 ellipse2d.jl 脚本。
修改的内容是再添加一个draw的定义!接受开始和结束角度的椭圆对象的函数(Julia 的多次分派也很棒)。
我认为最好的方法是定义新对象 ellipse_sector 和 circle_sector,它们与椭圆和圆形对象相同,但多了两个成员:start_angle 和 end_angle。然后应该实现相应的绘图功能。我想写信给 ImageDraw
包开发人员以提出这个建议,甚至让我进行这些更改,但我不知道 github.
相反,我的解决方案不修改任何现有对象,只是添加一个绘制方法!接受另外两个参数的函数:startAngle 和 endAngle。
这是要复制到 ellipse2d.jl 脚本末尾的代码:
function draw!(img::AbstractArray{T, 2}, ellipse::Ellipse, startAng::Real, endAng::Real, color::T) where T<:Colorant
# Solution to find out if an angle lies between two given ones, borrowed from:
#
# Make all angles to lie in [0, 2π)
# rem2pi(ϕ, RoundNearest) returns the remainder of the division by 2π in the range [−π,π]
# mod2pi returns the remainder of the division by 2π in the range [0,2π)
Angle1 = mod2pi(startAng)
Angle2 = mod2pi(endAng)
# make the angle from angle1 to angle2 to be <= 180 degrees
rAngle = mod2pi( mod2pi(Angle2 - Angle1) + 2π)
if rAngle >= π
Angle1, Angle2 = Angle2, Angle1 # Swaps the values
end # if
ys = Int[]
xs = Int[]
break_point = 0
if ellipse.fill == false
break_point = ((ellipse.ρy - ellipse.thickness) / ellipse.ρy) ^ 2 + ((ellipse.ρx - ellipse.thickness) / ellipse.ρx) ^ 2
end
for i in ellipse.center.y - ellipse.ρy : ellipse.center.y + ellipse.ρy
for j in ellipse.center.x - ellipse.ρx: ellipse.center.x + ellipse.ρx
y = i - ellipse.center.y
x = j - ellipse.center.x
val = (x / ellipse.ρy) ^ 2 + (y / ellipse.ρx) ^ 2
# atan(y, x) returns the angle in the correct quadrant [−π,π], not like atan(y/x)
# But make it to be in the range [0, 2π)by means of mod2pi()
ang = mod2pi( atan(y, x) )
# Test if the angle lies betwen the startAngle and the endAngle
if (Angle1 <= Angle2)
AngleIsBetween = ang >= Angle1 && ang <= Angle2
else
AngleIsBetween = ang >= Angle1 || ang <= Angle2
end # if
if val < 1 && val >= break_point && AngleIsBetween
push!(ys, i)
push!(xs, j)
end
end
end
for (yi, xi) in zip(ys, xs)
drawifinbounds!(img, yi, xi, color)
end
img
end