Line data Source code
1 : """
2 : Affine map `f(x) = A * x - b`
3 :
4 : f = affinemap(A, b)
5 : f(x) == A * x - b
6 :
7 : g = linearmap(f) # linear part A * x
8 : g = mapvector(f) # same as linearmap(f)
9 : g = mapunitvector(f) # plus normalization
10 : g = mapnormal(f) # map unit normals inv(A)' * x
11 :
12 : See also [`affinemap`](@ref), [`LinearMap`](@ref)
13 : """
14 : struct AffineMap{M, N, T, MN}
15 : A::SMatrix{M, N, T, MN}
16 : b::SVector{M, T}
17 : end
18 :
19 : """
20 : f = affinemap(A, b)
21 : f(x) == A * x - b
22 :
23 : affinemap(f) == f
24 : g = inv(f)
25 :
26 : Construct [`AffineMap`](@ref)
27 :
28 : See also [`AffineMap`](@ref), [`linearmap`](@ref)
29 : """
30 0 : affinemap(A::SMatrix{M, N, T, MN},
31 : b::SVector{M, T}) where {M, N, T, MN} =
32 : AffineMap{M, N, T, MN}(A, b)
33 :
34 0 : affinemap(t::AffineMap) = t
35 :
36 0 : function Base.inv(t::AffineMap{M, N, T, MN}) where {M, N, T, MN}
37 0 : iA = inv(t.A)
38 0 : affinemap(iA, -(iA * t.b))
39 : end
40 :
41 0 : (t::AffineMap{M, N, T, MN})(x) where {M, N, T, MN} =
42 : t.A * x - t.b # possibly more stable: A * (x - x0)
43 :
44 : """
45 : Linear map `f(x) = A * x`
46 :
47 : f = linearmap(A)
48 : f(x) == A * x
49 :
50 : linearmap(f) == f
51 :
52 : g = f' # adjoint
53 : g = inv(f) # inverse for maps (for quadratic A)
54 : g = inv(f')
55 : g = mapunitvector(f) # plus normalization
56 : g = mapnormal(f) # map unit normals inv(A)' * x
57 :
58 : See also [`AffineMap`](@ref), [`linearmap`](@ref)
59 : """
60 : struct LinearMap{M, N, T, MN}
61 : A::SMatrix{M, N, T, MN}
62 : end
63 :
64 0 : Base.inv(t::LinearMap{N, N, T, NN}) where {N, T, NN} =
65 : linearmap(inv(t.A))
66 :
67 0 : LinearAlgebra.adjoint(t::LinearMap{M, N, T, MN}) where {M, N, T, MN} =
68 : linearmap(t.A')
69 :
70 0 : linearmap(A::SMatrix{M, N, T, MN}) where {M, N, T, MN} =
71 : LinearMap{M, N, T, MN}(A)
72 :
73 0 : linearmap(t::AffineMap{M, N, T, MN}) where {M, N, T, MN} =
74 : linearmap(t.A)
75 :
76 0 : linearmap(t::LinearMap) = t
77 :
78 : """
79 : f = linearmap(A, b)
80 : f = linearmap(g::AffineMap)
81 : linearmap(f) == f
82 : f(x) == A * x
83 :
84 : Construct [`LinearMap`](@ref)
85 :
86 : See also [`LinearMap`](@ref), [`affinemap`](@ref)
87 : """ linearmap
88 :
89 0 : (t::LinearMap{M, N, T, MN})(x) where {M, N, T, MN} = t.A * x
90 :
91 0 : mapvector(t::AffineMap) = linearmap(t)
92 :
93 0 : mapvector(t::LinearMap) = t
94 :
95 : """
96 : f = affinemap(A, b)
97 : g = linearmap(f)
98 : g = mapvector(f)
99 :
100 : Synomym for [`linearmap`](@ref)
101 :
102 : See also [`LinearMap`](@ref), [`mapunitvector`](@ref),
103 : [`mapnormal`](@ref)
104 : """ mapvector
105 :
106 0 : function _normalized(x)
107 0 : len = norm(x)
108 0 : (len == 0) && return x
109 0 : x / len
110 : end
111 :
112 0 : mapunitvector(t::AffineMap) = _normalized ∘ mapvector(t)
113 :
114 0 : mapunitvector(t::LinearMap) = _normalized ∘ t'
115 :
116 : """
117 : f = affinemap(A, b)
118 : g = mapunitvector(f)
119 : g = mapunitvector(linearmap(f))
120 :
121 : *Nonlinear* map that composes [`linearmap`](@ref) and
122 : *normalization* of result.
123 :
124 : !!! note
125 : Null vectors are mapped to null vectors. They are
126 : *not* "normalized"!
127 :
128 : See also [`LinearMap`](@ref), [`mapvector`](@ref),
129 : [`mapnormal`](@ref)
130 : """ mapunitvector
131 :
132 :
133 0 : maptangentvector(t::AffineMap) = maptangentvector(linearmap(t))
134 :
135 0 : maptangentvector(t::LinearMap) = linearmap((t.A[@SVector([1, 2]), :]))'
136 :
137 : """
138 : Same as [`mapvector`](@ref) but use only dimensions `1:2`.
139 :
140 : Use case: [`tolocal`](@ref) maps to local `u,v,w` coordinates,
141 : map `u, v` to 3d vector in tangent space.
142 :
143 : See also [`mapvector`](@ref)
144 : """ maptangentvector
145 :
146 0 : maptangentunitvector(t::AffineMap) = _normalized ∘ maptangentvector(t)
147 :
148 0 : maptangentuntvector(t::LinearMap) = _normalized ∘ maptangentuntvector(t)
149 :
150 : """
151 : Same as [`mapunitvector`](@ref) but use only dimensions `1:2`.
152 :
153 : Use case: [`tolocal`](@ref) maps to local `u,v,w` coordinates,
154 : map `u, v` to 3d ("normalized") unit vector in tangent space.
155 :
156 : See also [`mapvector`](@ref)
157 : """ maptangentunitvector
158 :
159 0 : mapnormal(t::AffineMap{N, N, T, NN}) where {N, T, NN} =
160 : mapnormal(linearmap(t))
161 :
162 0 : mapnormal(t::LinearMap{N, N, T, NN}) where {N, T, NN} =
163 : linearmap(inv(t.A)')
164 :
165 : """
166 : f = affinemap(A, b)
167 : g = mapnormal(f)
168 : g = mapnormal(linearmap(f))
169 :
170 : *Nonlinear* map that maps normal vectors `n` with `inv(A)' * n`
171 : followed by *normalization*.
172 :
173 : !!! note
174 : Null vectors are mapped to null vectors. They are
175 : *not* "normalized"!
176 :
177 : See also [`LinearMap`](@ref), [`mapvector`](@ref),
178 : [`mapunitvector`](@ref)
179 : """ mapnormal
180 :
181 : """
182 : t = affinemap(A, b)
183 : mapvattr(t, mesh, Val(:x))
184 : mapvattr(mapnormal(t), mesh, Val(:n))
185 :
186 : mapvattr(x -> 2x, mesh, val(:myattr))
187 :
188 : Apply transformation on vertex attribute for all vertices.
189 :
190 : See also [`vattr`](@ref), [`affinemap`](@ref), [`linearmap`](@ref),
191 : [`mapunitvector`](@ref), [`normal`](@ref), [`maptangentvector`](@ref),
192 : [`maptangentunitvector`](@ref)
193 : """
194 0 : function mapvattr!(f, mesh::Mesh, ax)
195 0 : x = vattr(mesh, ax)
196 :
197 0 : for v in vertices(mesh)
198 0 : x[v] = f(x[v])
199 0 : end
200 : end
201 :
202 : # TODO: compose maps with ∘
|