-
Notifications
You must be signed in to change notification settings - Fork 4
/
subtyping.jl
83 lines (65 loc) · 2.26 KB
/
subtyping.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#_____________________________________________________________________
# Alice's code
#
using Statistics, ReusePatterns
abstract type AbstractPolygon end
abstract type Polygon <: AbstractPolygon end
mutable struct Concrete_Polygon <: Polygon
x::Vector{Float64}
y::Vector{Float64}
end
Polygon(args...; kw...) = Concrete_Polygon(args...; kw...)
# Retrieve the number of vertices, and their X and Y coordinates
vertices(p::Polygon) = length(p.x)
coords_x(p::Polygon) = p.x
coords_y(p::Polygon) = p.y
# Move, scale and rotate a polygon
function move!(p::Polygon, dx::Real, dy::Real)
p.x .+= dx
p.y .+= dy
end
function scale!(p::Polygon, scale::Real)
m = mean(p.x); p.x = (p.x .- m) .* scale .+ m
m = mean(p.y); p.y = (p.y .- m) .* scale .+ m
end
function rotate!(p::Polygon, angle_deg::Real)
θ = float(angle_deg) * pi / 180
R = [cos(θ) -sin(θ); sin(θ) cos(θ)]
x = p.x .- mean(p.x)
y = p.y .- mean(p.y)
(x, y) = R * [x, y]
p.x = x .+ mean(p.x)
p.y = y .+ mean(p.y)
end
#_____________________________________________________________________
# Bob's code
#
abstract type RegularPolygon <: Polygon end
mutable struct Concrete_RegularPolygon <: RegularPolygon
x::Vector{Float64}
y::Vector{Float64}
radius::Float64
end
RegularPolygon(args...; kw...) = Concrete_RegularPolygon(args...; kw...)
function RegularPolygon(n::Integer, radius::Real)
@assert n >= 3
θ = range(0, stop=2pi-(2pi/n), length=n)
c = radius .* exp.(im .* θ)
return RegularPolygon(real(c), imag(c), radius)
end
# Compute length of a side and the polygon area
side(p::RegularPolygon) = 2 * p.radius * sin(pi / vertices(p))
area(p::RegularPolygon) = side(p)^2 * vertices(p) / 4 / tan(pi / vertices(p))
function scale!(p::RegularPolygon, scale::Real)
invoke(scale!, Tuple{supertype(RegularPolygon), typeof(scale)}, p, scale) # call "super" method
p.radius *= scale # update internal state
end
# Attach a label to a polygon
mutable struct Named{T} <: AbstractPolygon
polygon::T
name::String
end
Named{T}(name, args...; kw...) where T = Named{T}(T(args...; kw...), name)
name(p::Named) = p.name
# Forward methods from `Named` to `Polygon`
@forward (Named, :polygon) RegularPolygon