Skip to content

Commit

Permalink
Add angle option, and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
eprovst committed Aug 14, 2023
1 parent fdef301 commit 7cac420
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 42 deletions.
4 changes: 2 additions & 2 deletions DomainColoringToy/Project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name = "DomainColoringToy"
uuid = "7cf40ad8-af6a-4ede-b3c6-2a9df3bce851"
authors = ["Evert Provoost <[email protected]>"]
version = "0.2.0"
version = "0.3.0"

[deps]
DomainColoring = "c24f3079-adb7-4533-8329-9f66732e5e85"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"

[compat]
DomainColoring = "0.4"
DomainColoring = "0.5"
GLMakie = "0.8"
julia = "1.6"
2 changes: 1 addition & 1 deletion DomainColoringToy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
</p>
<p>
Interactive domain colorings and checker plots of complex functions in Julia using smooth colors,
based on <a href="https://makie.org/">MakieGL</a>.
based on <a href="https://makie.org/">GLMakie</a>.
</p>
12 changes: 11 additions & 1 deletion DomainColoringToy/src/DomainColoringToy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ end
f :: "Complex -> Complex",
limits = (-1, 1, -1, 1);
pixels = (480, 480),
angle = true,
abs = false,
grid = false,
all = false,
Expand Down Expand Up @@ -137,6 +138,8 @@ to ``\\frac{2\\pi}{3}``, cyan to ``\\pi``, blue to
for both if only one number is provided. If either is `:auto`, the
viewport resolution is used.
- **`angle`** toggles coloring of the phase angle.
- **`abs`** toggles the plotting of the natural logarithm of the
magnitude as lightness ramps between level curves. If set to a number,
this will be used as base of the logarithm instead, if set to `Inf`,
Expand All @@ -157,13 +160,20 @@ function domaincolor(
f,
limits = (-1, 1, -1, 1);
pixels = (480, 480),
angle = true,
abs = false,
grid = false,
all = false,
)

# issue warning if everything is inactive
if Base.all(b -> b isa Bool && !b, [angle, abs, grid, all])
@warn "angle, abs, and grid are all false, domain coloring will be a constant color."
end

interactiveshadedplot(
f, w -> DC.domaincolorshader(w; abs, grid, all), limits, pixels)
f, w -> DC.domaincolorshader(w; angle, abs, grid, all),
limits, pixels)
end

"""
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DomainColoring"
uuid = "c24f3079-adb7-4533-8329-9f66732e5e85"
authors = ["Evert Provoost <[email protected]>"]
version = "0.4.1"
version = "0.5.0"

[deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Expand Down
3 changes: 3 additions & 0 deletions docs/src/usage/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,6 @@ The harshness of these white an black areas can be changed using the
```julia
domaincolor(z -> exp(1/z), .1, abs=(base=Inf, sigma=0.001))
```

Finally, if one wants any of the previous plots without coloring the
phase angle, they can use `angle = false`.
97 changes: 60 additions & 37 deletions src/DomainColoring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,24 @@ function shadedplot(

limits = _expandlimits(limits)

r = [limits[1], limits[2]]
i = [limits[3], limits[4]]
# images have inverted y and flip x and y in their storage
heatmap(r, reverse(i), renderimage(f, shader, limits, pixels)';
r = [limits[1], limits[2]]
i = [limits[4], limits[3]]
heatmap(r, i, renderimage(f, shader, limits, pixels)';
interpolate=true, axis=(autolimitaspect=1,),)
end

@enum GridType begin
CheckerGrid
LineGrid
end

# Logic for grid like plotting elements, somewhat ugly, but it works.
# `w` is the complex value, `checker` is a boolean for the others see
# `w` is the complex value, `type` is the type of grid to make
# `checkerplot`.
function _grid(
w,
checker;
type,
w;
real = false,
imag = false,
rect = false,
Expand Down Expand Up @@ -175,38 +179,45 @@ function _grid(
end

# set defaults
(real isa Bool && real) && (real = 1)
(imag isa Bool && imag) && (imag = 1)
(real isa Bool && real) && (real = 1)
(imag isa Bool && imag) && (imag = 1)
(angle isa Bool && angle) && (angle = 6)
(abs isa Bool && abs) && (abs = 1)
(abs isa Bool && abs) && (abs = 1)

g = 1.0
if real > 0 && isfinite(4*real*Base.real(w))
g *= sin(real*π*Base.real(w))
if real > 0
r = real * π * Base.real(w)
isfinite(r) && (g *= sin(r))
end
if imag > 0 && isfinite(4*imag*Base.imag(w))
g *= sin(imag*π*Base.imag(w))
if imag > 0
i = imag * π * Base.imag(w)
isfinite(i) && (g *= sin(i))
end
if angle > 0 && isfinite(angle*Base.angle(w))
checker && @assert iseven(angle) "Rate of angle has to be even."
g *= sin(angle/2*Base.angle(w))
if angle > 0
@assert mod(angle, 1) 0 "Rate of angle has to be an integer."
angle = round(angle)
(type == CheckerGrid) && @assert iseven(angle) "Rate of angle has to be even."

a = angle / 2 * Base.angle(w)
isfinite(a) && (g *= sin(a))
end
if abs > 0 && isfinite(4*abs*log(Base.abs(w)))
g *= sin(abs*π*log(Base.abs(w)))
if abs > 0
m = abs * π * log(Base.abs(w))
isfinite(m) && (g *= sin(m))
end

if checker
min(1, sign(g) + 1)
else
if type == CheckerGrid
float(g > 0)
elseif type == LineGrid
Base.abs(g)^0.06
end
end

_grid(w, checker, args::NamedTuple) = _grid(w, checker; args...)
_grid(type, w, args::NamedTuple) = _grid(type, w; args...)

_grid(w, checker, arg::Bool) = arg ? _grid(w, checker) : 1.0
_grid(type, w, arg::Bool) = arg ? _grid(type, w) : 1.0

_grid(w, checker, arg) = _grid(w, checker; rect=arg)
_grid(type, w, arg) = _grid(type, w; rect=arg)

# Implements the magnitude logic for `domaincolorshader`
# isnothing(transform) gives the default log, and saves us
Expand All @@ -215,7 +226,7 @@ _grid(w, checker, arg) = _grid(w, checker; rect=arg)
function _add_magnitude(
w,
c;
base = exp(1),
base = ,
transform = nothing,
sigma = 0.02,
)
Expand All @@ -231,11 +242,9 @@ function _add_magnitude(
isfinite(m) && (c = Lab(c.l + 20mod(m, 1) - 10, c.a, c.b))
else
m = log(abs(w))
if isfinite(m)
t = exp(-sigma*m^2)
g = 100(sign(m)/2 + .5)
c = Lab((1 - t)g + t*c.l, t*c.a, t*c.b)
end
t = isfinite(m) ? exp(-sigma*m^2) : 0.0
g = 100.0(m > 0)
c = Lab((1 - t)g + t*c.l, t*c.a, t*c.b)
end
end
return c
Expand Down Expand Up @@ -265,12 +274,15 @@ See [Phase Wheel](@ref) for more information.
"""
function labsweep(θ)
θ = mod(θ, 2π)
Lab(67 - 12cos(3θ), 46cos+ .4) - 3, 46sin+ .4) + 16)
Lab(67 - 12cos(3θ),
46cos+ .4) - 3,
46sin+ .4) + 16)
end

"""
DomainColoring.domaincolorshader(
w :: Complex;
angle = true,
abs = false,
grid = false,
all = false,
Expand All @@ -282,27 +294,29 @@ For documentation of the remaining arguments see [`domaincolor`](@ref).
"""
function domaincolorshader(
w;
angle = true,
abs = false,
grid = false,
all = false,
)

# user wants full domain coloring
if all
abs = true
grid = true
(angle isa Bool) && (angle = true)
(abs isa Bool) && (abs = true)
(grid isa Bool) && (grid = true)
end

# phase color
c = labsweep(angle(w))
c = angle ? labsweep(Base.angle(w)) : Lab(80.0, 0.0, 0.0)

# add magnitude
c = _add_magnitude(w, c, abs)

# add integer grid if requested
if !(grid isa Bool) || grid
# slightly overattenuate to compensate global darkening
g = 1.06_grid(w, false, grid)
g = 1.06_grid(LineGrid, w, grid)
c = mapc(x -> g*x, c)
end

Expand All @@ -314,6 +328,7 @@ end
f :: "Complex -> Complex",
limits = (-1, 1, -1, 1);
pixels = (720, 720),
angle = true,
abs = false,
grid = false,
all = false,
Expand All @@ -340,6 +355,8 @@ to ``\\frac{2\\pi}{3}``, cyan to ``\\pi``, blue to
real and imaginary axis, taking the same for both if only one number
is provided.
- **`angle`** toggles coloring of the phase angle.
- **`abs`** toggles the plotting of the natural logarithm of the
magnitude as lightness ramps between level curves. If set to a number,
this will be used as base of the logarithm instead, if set to `Inf`,
Expand All @@ -360,13 +377,19 @@ function domaincolor(
f,
limits = (-1, 1, -1, 1);
pixels = (720, 720),
angle = true,
abs = false,
grid = false,
all = false,
)

# issue warning if everything is inactive
if Base.all(b -> b isa Bool && !b, [angle, abs, grid, all])
@warn "angle, abs, and grid are all false, domain coloring will be a constant color."
end

shadedplot(f, w -> domaincolorshader(
w; abs, grid, all
w; angle, abs, grid, all
), limits, pixels)
end

Expand Down Expand Up @@ -497,7 +520,7 @@ function checkerplotshader(
polar = false,
)

g = _grid(w, true; real, imag, rect, angle, abs, polar)
g = _grid(CheckerGrid, w; real, imag, rect, angle, abs, polar)
return Gray(0.9g + 0.08)
end

Expand Down

0 comments on commit 7cac420

Please sign in to comment.