Skip to content

Commit 1e7aecf

Browse files
committed
A spider struct and a recipe to plot them
1 parent 4067b8e commit 1e7aecf

File tree

2 files changed

+70
-73
lines changed

2 files changed

+70
-73
lines changed

spiders/ShowSpider.jl

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,35 @@ using GLMakie
22
using ColorSchemes
33
include("Spiders.jl")
44

5-
function spideriterates(angle::Rational,frames::Int)
6-
info = SpiderInfo(angle)
7-
8-
list = [standardlegs(angle)]
5+
@recipe(SpiderPlot,S) do scene
6+
Theme()
7+
end
98

10-
for i in 1:frames-1
11-
SL = list[end]
12-
push!(list,spidermap(info,SL))
9+
function Makie.plot!(myplot::SpiderPlot)
10+
n = length(myplot.S[].legs)
11+
for (j ,leg) in enumerate(myplot.S[].legs)
12+
lines!(myplot, real(leg),imag(leg),color = get(ColorSchemes.viridis, float(j)/float(n)))
13+
text!(myplot, real(leg[end]),imag(leg[end]);text = "$j")
1314
end
14-
return list
15+
limits!(-6,4,-4,4)
16+
#why can we use the above function but cannot do other things like hidespines?
17+
return myplot
1518
end
1619

20+
1721
function showspider(angle::Rational,frames::Int)
1822

19-
list = spideriterates(angle,frames)
23+
S0 = standardspider(angle)
24+
25+
list = spideriterates(S0,frames)
2026

2127
fig = Figure()
2228
ax = Axis(fig[1, 1])
23-
r = 8
24-
xlims!(-r,r)
25-
ylims!(-r,r)
26-
27-
n = length(list[end])
2829

2930
record(fig,"test.gif",1:frames; framerate = 3) do i
3031
empty!(ax)
31-
spider = list[i]
32-
for (j ,leg) in enumerate(spider)
33-
lines!(real(leg),imag(leg),color = get(ColorSchemes.viridis, float(j)/float(n)))
34-
text!(real(leg[1]),imag(leg[1]);text = "$j")
35-
end
32+
spiderplot!(ax,list[i])
3633
end
37-
38-
return list[end][2][end]/2
3934

4035
end
4136

spiders/Spiders.jl

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,29 @@ using IterTools
22
include("SpiderFuncs.jl")
33
include("../sequences/AngleDoubling.jl")
44

5-
struct SpiderInfo
6-
orbit::Vector{Rational}
7-
kneading_sequence::Vector{Char}
8-
preperiod::Int
5+
struct Spider
6+
angle::Rational
7+
orbit::Sequence{Rational}
8+
kneading_sequence::Sequence{Char}
9+
legs::Vector{Vector{ComplexF64}}
910
end
10-
1111

12-
function SpiderInfo(theta::Rational)
12+
function Base.show(io::IO, S::Spider)
13+
npoints = sum([length(leg) for leg in S.legs])
14+
return println("A "*repr(S.angle)*"-spider with kneading sequence "*repr(S.kneading_sequence)*" and "*repr(npoints)*" points.")
15+
end
1316

17+
function standardspider(theta::Rational)
1418
orb = orbit(theta)
15-
K = kneadingsequence(theta)
16-
17-
return SpiderInfo(orb.items,K.items,K.preperiod)
18-
19+
K = thetaitinerary(theta,orb) #the kneading sequence is calculated like so to avoid recalculating the orbit of theta
20+
legs = standardlegs(orb)
21+
return Spider(theta,orb,K,legs)
1922
end
2023

21-
function standardlegs(SpIf::SpiderInfo)
24+
function standardlegs(orbit::Sequence)
2225
r = collect(LinRange(100,1,10)) #NOTE - it may be better to keep this as a 'linrange' but I don't understand what that means
2326
legs = Vector{ComplexF64}[]
24-
for theta in SpIf.orbit
27+
for theta in orbit.items
2528
push!(legs,(cos(theta*2*pi)+1.0im*sin(theta*2*pi)) .* r)
2629
end
2730
legs[1] = legs[1] .- legs[1][end]
@@ -58,16 +61,16 @@ function stats(legs::Vector{Vector{ComplexF64}})
5861
println(radius)
5962
end
6063

61-
function spidermap(S::SpiderInfo, Legs::Vector{Vector{ComplexF64}})
62-
λ = Legs[2][end] #the parameter of our polynomial map z -> λ(1+z/2)^2
63-
a = (angle(Legs[1][1]/λ)/(2*pi)+1)%1 #the angle whose halves will define the boundary between regions A and B at infinity. in full turns
64+
function mapspider!(S::Spider)
65+
λ = S.legs[2][end] #the parameter of our polynomial map z -> λ(1+z/2)^2
66+
a = (angle(S.legs[1][1]/λ)/(2*pi)+1)%1 #the angle whose halves will define the boundary between regions A and B at infinity. in full turns
6467

6568
n = length(S.orbit)
6669

6770
newLegs = Vector{Vector{ComplexF64}}(undef,n)
6871

6972
#leg 1 goes first
70-
newLegs[1] = path_sqrt(Legs[2]./λ)
73+
newLegs[1] = path_sqrt(S.legs[2]./λ)
7174

7275
theta1 = (angle(newLegs[1][1])/(2*pi)+1)%1 #gives the angle of the shoulder in full turns
7376
#this angle lays in region A by definition.
@@ -82,75 +85,75 @@ function spidermap(S::SpiderInfo, Legs::Vector{Vector{ComplexF64}})
8285

8386
for ii in 2:n-1
8487
#first find the right half plane preimage of the shoulder
85-
u = sqrt(Legs[ii+1][1]./λ)
88+
u = sqrt(S.legs[ii+1][1]./λ)
8689
thetau = (angle(u)/(2*pi)+1)%1
8790

8891
if a/2 < thetau && thetau < (a+1)/2 #thetau is in the connected region
8992
if S.kneading_sequence[ii] == cregion #then this is the correct preimage
90-
newLegs[ii] = path_sqrt(Legs[ii+1]./λ)
93+
newLegs[ii] = path_sqrt(S.legs[ii+1]./λ)
9194
else
92-
newLegs[ii] = -1 .* path_sqrt(Legs[ii+1]./λ)
95+
newLegs[ii] = -1 .* path_sqrt(S.legs[ii+1]./λ)
9396
end
9497
else #thetau is in the disconnected region
9598
if S.kneading_sequence[ii] == dregion #then this is the correct preimage
96-
newLegs[ii] = path_sqrt(Legs[ii+1]./λ)
99+
newLegs[ii] = path_sqrt(S.legs[ii+1]./λ)
97100
else
98-
newLegs[ii] = -1 .* path_sqrt(Legs[ii+1]./λ)
101+
newLegs[ii] = -1 .* path_sqrt(S.legs[ii+1]./λ)
99102
end
100103
end
101104
end
102105

103106
#we will break into periodic and preperiodic cases for the last leg
104-
if S.preperiod == 0 #periodic
105-
u = sqrt(Legs[1][1]./λ)
107+
if S.orbit.preperiod == 0 #periodic
108+
u = sqrt(S.legs[1][1]./λ)
106109
thetau = (angle(u)/(2*pi)+1)%1
107110

108111
if abs2(thetau - a/2) < abs2(thetau - (a+1)/2)
109112
if cregion == 'A'
110-
if S.kneading_sequence[end] == '2'
111-
newLegs[end] = path_sqrt(Legs[1]./λ)
113+
if S.kneading_sequence.items[end] == '2'
114+
newLegs[end] = path_sqrt(S.legs[1]./λ)
112115
else
113-
newLegs[end] = -1 .*path_sqrt(Legs[1]./λ)
116+
newLegs[end] = -1 .*path_sqrt(S.legs[1]./λ)
114117
end
115118
else
116-
if S.kneading_sequence[end] == '1'
117-
newLegs[end] = path_sqrt(Legs[1]./λ)
119+
if S.kneading_sequence.items[end] == '1'
120+
newLegs[end] = path_sqrt(S.legs[1]./λ)
118121
else
119-
newLegs[end] = -1 .*path_sqrt(Legs[1]./λ)
122+
newLegs[end] = -1 .*path_sqrt(S.legs[1]./λ)
120123
end
121124
end
122125
else
123126
if cregion == 'A'
124-
if S.kneading_sequence[end] == '1'
125-
newLegs[end] = path_sqrt(Legs[1]./λ)
127+
if S.kneading_sequence.items[end] == '1'
128+
newLegs[end] = path_sqrt(S.legs[1]./λ)
126129
else
127-
newLegs[end] = -1 .*path_sqrt(Legs[1]./λ)
130+
newLegs[end] = -1 .*path_sqrt(S.legs[1]./λ)
128131
end
129132
else
130-
if S.kneading_sequence[end] == '2'
131-
newLegs[end] = path_sqrt(Legs[1]./λ)
133+
if S.kneading_sequence.items[end] == '2'
134+
newLegs[end] = path_sqrt(S.legs[1]./λ)
132135
else
133-
newLegs[end] = -1 .*path_sqrt(Legs[1]./λ)
136+
newLegs[end] = -1 .*path_sqrt(S.legs[1]./λ)
134137
end
135138
end
136139
end
137140

138141
else #preperiodic
139142
p = S.preperiod
140-
u = sqrt(Legs[p+1][1]./λ)
143+
u = sqrt(S.legs[p+1][1]./λ)
141144
thetau = (angle(u)/(2*pi)+1)%1
142145

143146
if a/2 < thetau && thetau < (a+1)/2 #thetau is in the connected region
144-
if S.kneading_sequence[end] == cregion #then this is the correct preimage
145-
newLegs[end] = path_sqrt(Legs[p+1]./λ)
147+
if S.kneading_sequence.items[end] == cregion #then this is the correct preimage
148+
newLegs[end] = path_sqrt(S.legs[p+1]./λ)
146149
else
147-
newLegs[end] = -1 .* path_sqrt(Legs[p+1]./λ)
150+
newLegs[end] = -1 .* path_sqrt(S.legs[p+1]./λ)
148151
end
149152
else #thetau is in the disconnected region
150-
if S.kneading_sequence[end] == dregion #then this is the correct preimage
151-
newLegs[end] = path_sqrt(Legs[p+1]./λ)
153+
if S.kneading_sequence.items[end] == dregion #then this is the correct preimage
154+
newLegs[end] = path_sqrt(S.legs[p+1]./λ)
152155
else
153-
newLegs[end] = -1 .* path_sqrt(Legs[p+1]./λ)
156+
newLegs[end] = -1 .* path_sqrt(S.legs[p+1]./λ)
154157
end
155158
end
156159
end
@@ -161,18 +164,17 @@ function spidermap(S::SpiderInfo, Legs::Vector{Vector{ComplexF64}})
161164
newLegs .*= (2.0+0.0im)
162165

163166
grow!(newLegs,10,10)
164-
165-
return newLegs
167+
for ii in eachindex(S.legs)
168+
S.legs[ii] = copy(newLegs[ii]) #done in this way so we can mutate S without mutating S
169+
end
170+
return S
166171
end
167172

168-
function spideriterate(angle::Rational,frames::Int)
169-
info = SpiderInfo(angle)
170-
171-
list = [standardlegs(angle)]
173+
function spideriterates(S0::Spider,n_iter::Int)
174+
list = [deepcopy(S0)]
172175

173-
for i in 1:frames-1
174-
SL = list[end]
175-
push!(list,spidermap(info,SL))
176+
for i in 1:n_iter
177+
push!(list,deepcopy(mapspider!(S0)))
176178
end
177-
return list[end][2][end]/2
179+
return list
178180
end

0 commit comments

Comments
 (0)