# ファイル名 plotter.jl
using Plots
# 開始
function plotbegin(; w = 600, h = 600)
pyplot(grid=false, aspect_ratio=1, size=(w, h),
xlabel="", ylabel="", label="")
plt = plot(showaxis=false)
end
# プロット領域((x1, y1), (x2, y2) を対角座標とする矩形内)の設定
function plotlimit(x1, y1, x2, y2)
plot!(xlims=(x1, x2), ylims=(y1, y2))
end
# 終了
function plotend()
plot!()
end
# 座標ベクトル x, y による折線
function plotline(x::Vector{Float64}, y::Vector{Float64};
col=:black, lty=:solid, lwd=1)
plot!(x, y, linecolor=col, linestyle=lty, linewidth=lwd)
end
# (x1, y1) - (x2, y2) の線分
function plotline(x1, y1, x2, y2; col=:black, lty=:solid, lwd=1)
plot!([x1, x2], [y1, y2], linecolor=col, linestyle=lty, linewidth=lwd)
end
# (x1, y) - (x2, y) の水平線分
function plothline(x1, x2, y; col=:black, lty=:solid, lwd=1)
plot!([x1, x2], [y, y], linecolor=col, linestyle=lty, linewidth=lwd)
end
# (x, y1) - (x, y2) の垂直線分
function plotvline(x, y1, y2; col=:black, lty=:solid, lwd=1)
plot!([x, x], [y1, y2], linecolor=col, linestyle=lty, linewidth=lwd)
end
# (x1, y1), (x2, y2) を対角座標とする矩形
function plotbox(x1, y1, x2, y2; col=:black, lty=:solid, lwd=1, fcol="")
if fcol == ""
plot!([x1, x2, x2, x1, x1], [y1, y1, y2, y2, y1], linecolor=col,
linestyle=lty, linewidth=lwd)
else
plot!([x1, x2, x2, x1, x1], [y1, y1, y2, y2, y1], linecolor=col,
linestyle=lty, seriestype=:shape, linewidth=lwd, fillcolor=fcol)
end
end
# (ox, oy) を原点とする半径 r の円(円弧)。fcol を指定すると塗りつぶし。
function plotcircle(ox, oy, r; startangle=0, endangle=360,
col=:black, lty=:solid, lwd=1, fcol="")
plotellipse(ox, oy, r, r, φ=0, startangle=startangle,
endangle=endangle, col=col, lty=lty, lwd=lwd, fcol=fcol)
end
# 度をラジアンに変換する
radian(degree) = degree / 180 * π
# (ox, oy) を中心,ra, rb を半径とする楕円(楕円弧)。fcol を指定すると塗りつぶし。
function plotellipse(ox, oy, ra, rb; φ=0, startangle=0, endangle=360,
length=100, col=:black, lty=:solid, lwd=1, fcol="")
θ = vcat(range(radian(startangle), radian(endangle),
length=length), radian(endangle))
if φ == 0
if fcol == ""
plot!(ra .* cos.(θ) .+ ox, rb .* sin.(θ) .+ oy,
linecolor=col, linestyle=lty, linewidth=lwd)
else
plot!(ra .* cos.(θ) .+ ox, rb .* sin.(θ) .+ oy,
linecolor=col, linestyle=lty, linewidth=lwd,
seriestype=:shape, fillcolor=fcol)
end
else
x = ra .* cos.(θ)
y = rb .* sin.(θ)
φ = radian(φ)
cosine = cos(φ)
sine = sin(φ)
if fcol == ""
plot!(cosine .* x .- sine .* y .+ ox,
sine .* x .+ cosine .* y .+ oy,
linecolor=col, linestyle=lty, linewidth=lwd)
else
plot!(cosine .* x .- sine .* y .+ ox,
sine .* x .+ cosine .* y .+ oy,
linecolor=col, linestyle=lty, linewidth=lwd,
seriestype=:shape, fillcolor=fcol)
end
end
end
# 任意の多角形。fcol を指定すると塗りつぶし。
function plotpolygon(x, y; col=:black, lty=:solid, lwd=1, fcol="")
x = vcat(x, x[1])
y = vcat(y, y[1])
if fcol == ""
plot!(x, y, linecolor=col, linestyle=lty, linewidth=lwd)
else
plot!(x, y, linecolor=col, linestyle=lty, linewidth=lwd,
seriestype=:shape, fillcolor=fcol)
end
end
# (x1, y1) を描き始め,一辺の長さ l の正 n 多角形。fcol を指定すると塗りつぶし。
function plotpolygon1(x1, y1, l, n; col=:black, lty=:solid, lwd=1, fcol="")
θ = range(0, 2π, length=n+1)
x = fill(float(x1), n+1)
y = fill(float(y1), n+1)
for i = 2:n
x[i] = x[i-1]+l*cos(θ[i])
y[i] = y[i-1]+l*sin(θ[i])
end
if fcol == ""
plot!(x, y, linecolor=col, linestyle=lty, linewidth=lwd)
else
plot!(x, y, linecolor=col, linestyle=lty,
seriestype=:shape, fillcolor=fcol, linewidth=lwd)
end
end
# (ox, oy) を中心,r を半径とする円に内接する正 n 多角形。fcol を指定すると塗りつぶし。
function plotpolygon2(ox, oy, r, n; φ=90, col=:black, lty=:solid, lwd=1, fcol="")
θ = range(0, 2π, length=n+1) .+ radian(φ)
if fcol == ""
plot!(r .* cos.(θ) .+ ox, r .* sin.(θ) .+ oy,
linecolor=col, linestyle=lty, linewidth=lwd)
else
plot!(r .* cos.(θ) .+ ox, r .* sin.(θ) .+ oy,
linecolor=col, linestyle=lty, linewidth=lwd,
seriestype=:shape, fillcolor=fcol)
end
end
# (x1,y1) - (x2, y2) の矩形範囲に格子を描く。間隔は wx, wy。
function plotgrid(x1, y1, x2, y2, wx; wy=wx, col=:gray, lty=:dot, lwd=1)
X1 = min(x1, x2)
X2 = max(x1, x2)
Y1 = min(y1, y2)
Y2 = max(y1, y2)
for i = 0:fld(abs(X2-X1), wx)
plot!([X1+wx*i, X1+wx*i], [Y1, Y2], linecolor=col,
linestyle=lty, linewidth=lwd)
end
for i = 0:fld(abs(y2-y1), wy)
plot!([X1, X2], [Y1+wy*i, Y1+wy*i], linecolor=col,
linestyle=lty, linewidth=lwd)
end
end
# 二点 (x1, y1), (x2, y2) を通る半径 r の円弧(短い方)を描く。
# 短い方の円弧も,円の中心が 2 つあるので,x1 = x2 の場合は,右か左いずれの中心を使うかを :right, :left で示す。
# x1 ≠ x2 の場合は,上か下いずれの中心を使うかを :upper, :lower で示す。
function plotarc(x1, y1, x2, y2, r; udrl="", col=:black, lwd=1)
function adjust(φ, x1, y1, x3, y3)
if x1 >= x3 && y1 >= y3 # 第1象限
return φ
elseif x1 >= x3 && y1 < y3 # 第4象限
return 360-φ
elseif x1 < x3 && y1 >= y3 # 第2象限
return 180-φ
elseif x1 < x3 && y1 < y3 # 第3象限
return 180+φ
end
end
if y1 > y2
x1, y1, x2, y2 = x2, y2, x1, y1
end
x31 = x32 = y31 = y32 = NaN
if x1 == x2
w = r^2 - (y2 - y1)^2 / 4
if w >= 0
t0 = sqrt(w)
x31 = x1 + t0
x32 = x1 - t0
y31 = y32 = (y1 + y2) / 2
θ = asind(abs(y2 - y32) / r)
if udrl == :right
plotcircle(x31, y31, r, startangle=180 - θ, endangle=180 + θ, col=col, lwd=lwd)
elseif udrl == :left
plotcircle(x32, y32, r, startangle=-θ, endangle=θ, col=col, lwd=lwd)
else
error("if x1 == x2, udrl must be ':right' or ':left'")
end
end
else
t1 = x1^2 - x2^2 + y1^2 - y2^2
t5 = x1 - x2
t2 = y2 - y1
t3 = t5^2 + t2^2
t4 = t3 - 4r^2
w = -t3*t4
if w > 0
t6 = y1/2 + y2/2
t7 = sqrt(w)*t5/2t3
y31 = t6 - t7
y32 = t6 + t7
if y31 < y32
y31, y32 = y32, y31
end
x31 = (t1 + 2t2*y31)/2t5
x32 = (t1 + 2t2*y32)/2t5
posy1 = y31 - (y2 - y1)/(x2 - x1)*(x31 - x1) - y1
posy2 = y32 - (y2 - y1)/(x2 - x1)*(x32 - x1) - y1
if udrl == :upper
x3, y3 = x31, y31
else#if udrl == :lower
x3, y3 = x32, y32
end
#println("(x1, y1) = ($x1, $y1), (x2, y2) = ($x2, $y2), (x3, y3) = ($x3, $y3)")
φ = adjust(asind(abs(y1 - y3) / r), x1, y1, x3, y3)
θ = adjust(asind(abs(y2 - y3) / r), x2, y2, x3, y3)
θ - φ > 180 && (θ -= 360)
φ - θ > 180 && (φ -= 360)
#println("posy1 = $posy1, posy2 = $posy2, θ = $θ, φ = $φ")
plotcircle(x3, y3, r, startangle=φ, endangle=θ, col=col, lwd=lwd)
end
end
x31, y31, x32, y32
end