-
Notifications
You must be signed in to change notification settings - Fork 87
/
Copy pathvectors.jl
94 lines (78 loc) · 2.93 KB
/
vectors.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
84
85
86
87
88
89
90
91
92
93
94
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------
"""
Vec(x₁, x₂, ..., xₙ)
Vec((x₁, x₂, ..., xₙ))
Vec([x₁, x₂, ..., xₙ])
Vec{Dim,T}(x₁, x₂, ..., xₙ)
Vec{Dim,T}((x₁, x₂, ..., xₙ))
Vec{Dim,T}([x₁, x₂, ..., xₙ])
A vector in `Dim`-dimensional space with coordinates of type `T`.
By default, integer coordinates are converted to Float64.
A vector can be obtained by subtracting two [`Point`](@ref) objects.
## Examples
```julia
A = Point(0.0, 0.0)
B = Point(1.0, 0.0)
v = B - A
# 2D vectors
Vec(0.0, 1.0) # double precision as expected
Vec(0f0, 1f0) # single precision as expected
Vec(0, 0) # Integer is converted to Float64 by design
Vec2(0, 1) # explicitly ask for double precision
Vec2f(0, 1) # explicitly ask for single precision
# 3D vectors
Vec(1.0, 2.0, 3.0) # double precision as expected
Vec(1f0, 2f0, 3f0) # single precision as expected
Vec(1, 2, 3) # Integer is converted to Float64 by design
Vec3(1, 2, 3) # explicitly ask for double precision
Vec3f(1, 2, 3) # explicitly ask for single precision
```
### Notes
- A `Vec` is a subtype of `StaticVector` from StaticArrays.jl
- Type aliases are `Vec1`, `Vec2`, `Vec3`, `Vec1f`, `Vec2f`, `Vec3f`
"""
struct Vec{Dim,T} <: StaticVector{Dim,T}
coords::NTuple{Dim,T}
Vec{Dim,T}(coords::NTuple{Dim,T}) where {Dim,T} = new{Dim,T}(coords)
Vec{Dim,T}(coords::NTuple{Dim,T}) where {Dim,T<:Integer} = new{Dim,Float64}(coords)
end
# convenience constructors
Vec{Dim,T}(coords...) where {Dim,T} = Vec{Dim,T}(coords)
function Vec{Dim,T}(coords::Tuple) where {Dim,T}
checkdim(Vec{Dim,T}, coords)
Vec{Dim,T}(NTuple{Dim,T}(coords))
end
function Vec{Dim,T}(coords::AbstractVector) where {Dim,T}
checkdim(Vec{Dim,T}, coords)
Vec{Dim,T}(NTuple{Dim,T}(coords))
end
Vec(coords...) = Vec(coords)
Vec(coords::Tuple) = Vec(promote(coords...))
Vec(coords::NTuple{Dim,T}) where {Dim,T} = Vec{Dim,T}(coords)
Vec(coords::AbstractVector{T}) where {T} = Vec{length(coords),T}(coords)
# StaticVector constructors
Vec(coords::StaticVector{Dim,T}) where {Dim,T} = Vec{Dim,T}(coords)
Vec{Dim,T}(coords::StaticVector) where {Dim,T} = Vec{Dim,T}(Tuple(coords))
# type aliases for convenience
const Vec1 = Vec{1,Float64}
const Vec2 = Vec{2,Float64}
const Vec3 = Vec{3,Float64}
const Vec1f = Vec{1,Float32}
const Vec2f = Vec{2,Float32}
const Vec3f = Vec{3,Float32}
# StaticVector interface
Base.Tuple(v::Vec) = getfield(v, :coords)
Base.getindex(v::Vec, i::Int) = getindex(getfield(v, :coords), i)
function StaticArrays.similar_type(::Type{<:Vec}, ::Type{T}, ::Size{S}) where {T,S}
L = prod(S)
N = length(S)
isone(N) && !(T<:Integer) ? Vec{L,T} : SArray{Tuple{S...},T,N,L}
end
# utils
function checkdim(::Type{Vec{Dim,T}}, coords) where {Dim,T}
if Dim ≠ length(coords)
throw(DimensionMismatch("Invalid dimension."))
end
end