Line data Source code
1 : """
2 : Polygonal surface mesh based on a half-edge data structure.
3 :
4 : The type of the mesh is defined by its vertex/ face/ half-edge/ edge
5 : attributes `VA`, `FA`, `HA`, `EA` which are [`AbstractVAttr`](@ref),
6 : [`AbstractFAttr`](@ref), [`AbstractHAttr`](@ref),
7 : [`AbstractEAttr`](@ref), respectively.
8 :
9 : The state of the half-edge data structure is defined as part of the
10 : attributes ([`link`](@ref)).
11 :
12 : !!! tip
13 : Use [`createmesh`](@ref), [`similar(::Mesh)`](@ref) and [`clone`](@ref)
14 : to construct a new mesh.
15 :
16 : See also [`createmesh`](@ref), [`similar`](@ref), [`clone`](@ref),
17 : [`vattr`](@ref), [`fattr`](@ref), [`hattr`](@ref), [`eattr`](@ref)
18 : """
19 : struct Mesh{VA <: AbstractVAttr,
20 : FA <: AbstractFAttr,
21 : HA <: AbstractHAttr,
22 : EA <: AbstractEAttr}
23 : v::VA
24 : f::FA
25 : h::HA
26 : e::EA
27 :
28 64 : Mesh{V, F, H, E}(v::V, f::F, h::H, e::E) where {V, F, H, E} =
29 : new(v, f, h, e)
30 : end
31 :
32 : """
33 : mesh = createmesh(v, g, h, e)
34 :
35 : Create mesh with attributes `v` (vertices), `f` (faces), `h`
36 : (half-edges), `e` (edges).
37 :
38 : !!! note
39 : The attributes determine the **type** of `mesh`
40 :
41 : !!! tip
42 : Use [`similar(::Mesh)`](@ref) for constructing an empty mesh f
43 : identical type (i.e., identical attribute lists including
44 : enabled state of attributes).
45 :
46 : # Example
47 :
48 : Create `mesh` with vertex attributes for position `:x` and normals
49 : `:n`, face normals `:n` and color `:c`, no attributes for half-edges,
50 : and an edge attribute `:feature`. A default value `:red` is specified
51 : for face color `:c`, and this attribute is disabled after construction.
52 :
53 : mesh = createmesh((:x => SVector{3, Float64}, :n => SVector{3, Float64}),
54 : (:n => SVector{3, Float64},
55 : :c => specifyattr(Symbol, enabled=false, x0=:red)),
56 : (),
57 : (:feature => Bool))
58 :
59 : See also [`similar`](@ref), [`Mesh`](@ref)
60 : """
61 4 : function createmesh(v, f, h, e)
62 4 : va = createvattr(v)
63 4 : fa = createfattr(f)
64 4 : ha = createhattr(h)
65 4 : ea = createeattr(e)
66 :
67 4 : Mesh{typeof(va), typeof(fa), typeof(ha), typeof(ea)}(va, fa, ha, ea)
68 : end
69 :
70 : """
71 : mc = clone(mesh)
72 :
73 : Create deep copy of mesh but don't copy any disabled attributes.
74 : In contrast to [`compact`](@ref) this method preserves handles and their
75 : [`isused`](@ref) state.
76 :
77 : See also [`compact`](@ref)
78 : """
79 4 : function clone(mesh::Mesh{V, F, H, E}) where {V, F, H, E}
80 4 : Mesh{V, F, H, E}(clone(vattr(mesh)), clone(fattr(mesh)),
81 : clone(hattr(mesh)), clone(eattr(mesh)))
82 : end
83 :
84 : """
85 : mesh2 = similar(mesh)
86 :
87 : Create `mesh2` with identical same lists and identical type as `mesh`.
88 : The enabled state of attributes and the default values are copied
89 : from `mesh`.
90 :
91 : See also [`createmesh`](@ref)
92 : """
93 54 : function Base.similar(mesh::Mesh{V, F, H, E}) where {V, F, H, E}
94 54 : Mesh{V, F, H, E}(similar(vattr(mesh)), similar(fattr(mesh)),
95 : similar(hattr(mesh)), similar(eattr(mesh)))
96 : end
97 :
98 : """
99 : empty!(mesh)
100 :
101 : Remove all vertices, i.e., all mesh elements.
102 : """
103 0 : function Base.empty!(mesh::Mesh)
104 0 : empty!(vattr(mesh))
105 0 : empty!(fattr(mesh))
106 0 : resizeattr!(attrs(hattr(mesh)), 0)
107 0 : empty!(eattr(mesh))
108 :
109 0 : mesh
110 : end
111 :
112 : """
113 : link(vattr(mesh))
114 : link(fattr(mesh))
115 : link(hattr(mesh))
116 : link(eattr(mesh))
117 :
118 : Access attribute that stores the state of the half-edge data
119 : structure, which "links" mesh elements.
120 :
121 : !!! note
122 : For internal use only!
123 :
124 : See also [`vattr`](@ref), [`fattr`](@ref), [`hattr`](@ref), [`eattr`](@ref)
125 : """
126 3630293 : link(ma::ManagedAttributes) = attrs(ma)._link # attrs(ma, :_link)
127 :
128 428797 : vattr(mesh::Mesh) = mesh.v
129 434080 : fattr(mesh::Mesh) = mesh.f
130 3229576 : hattr(mesh::Mesh) = mesh.h
131 3629949 : eattr(mesh::Mesh) = mesh.e
132 :
133 27 : vattr(mesh::Mesh, name::Symbol) = attrs(vattr(mesh), name)
134 3 : fattr(mesh::Mesh, name::Symbol) = attrs(fattr(mesh), name)
135 1 : hattr(mesh::Mesh, name::Symbol) = attrs(hattr(mesh), name)
136 1 : eattr(mesh::Mesh, name::Symbol) = attrs(eattr(mesh), name)
137 :
138 72 : vattr(mesh::Mesh, name::Val{S}) where {S} = attrs(vattr(mesh), S)
139 4 : fattr(mesh::Mesh, name::Val{S}) where {S} = attrs(fattr(mesh), S)
140 1 : hattr(mesh::Mesh, name::Val{S}) where {S} = attrs(hattr(mesh), S)
141 1 : eattr(mesh::Mesh, name::Val{S}) where {S} = attrs(eattr(mesh), S)
142 :
143 39 : vattr(::Mesh, a::Attribute{T, VHnd}) where {T} = a
144 1 : fattr(::Mesh, a::Attribute{T, FHnd}) where {T} = a
145 1 : hattr(::Mesh, a::Attribute{T, HHnd}) where {T} = a
146 1 : eattr(::Mesh, a::Attribute{T, EHnd}) where {T} = a
147 :
148 2 : function vattr(mesh::Mesh, name, default)
149 2 : hasvattr(mesh, name) && return vattr(mesh, name)
150 1 : default
151 : end
152 :
153 2 : function fattr(mesh::Mesh, name, default)
154 2 : hasfattr(mesh, name) && return fattr(mesh, name)
155 1 : default
156 : end
157 :
158 2 : function hattr(mesh::Mesh, name, default)
159 2 : hashattr(mesh, name) && return hattr(mesh, name)
160 1 : default
161 : end
162 :
163 2 : function eattr(mesh::Mesh, name, default)
164 2 : haseattr(mesh, name) && return eattr(mesh, name)
165 1 : default
166 : end
167 :
168 : """
169 : list = vattr(mesh)
170 : attr = vattr(mesh, name)
171 : attr = vattr(mesh, Val(name)) # fast & type-safe if name is a literal
172 : attr = vattr(mesh, attr) # identity
173 :
174 : attr = vattr(mesh, name, default) # checks hasvattr
175 :
176 : Get vertex attribute list from `mesh` or particular vertex attribute
177 : `name`. The optional `default` argument is returned if
178 : [`hasvattr`](@ref) yields `false` similar to `Base.get`.
179 :
180 : Example:
181 :
182 : x = vattr(mesh, :x)
183 :
184 : See also [`fattr`](@ref), [`hattr`](@ref), [`eattr`](@ref)
185 : """ vattr
186 :
187 : """
188 : list = fattr(mesh)
189 : attr = fattr(mesh, name)
190 : attr = fattr(mesh, Val(name)) # fast & type-safe if name is a literal
191 : attr = fattr(mesh, attr) # identity
192 :
193 : attr = fattr(mesh, name, default) # checks hasfattr
194 :
195 : Get face attribute list from `mesh` or particular vertex attribute
196 : `name`. The optional `default` argument is returned if
197 : [`hasfattr`](@ref) yields `false` similar to `Base.get`.
198 :
199 : See also [`vattr`](@ref), [`hattr`](@ref), [`eattr`](@ref)
200 : """ fattr
201 :
202 : """
203 : list = hattr(mesh)
204 : attr = hattr(mesh, name)
205 : attr = hattr(mesh, Val(name)) # fast & type-safe if name is a literal
206 : attr = hattr(mesh, attr) # identity
207 :
208 : attr = hattr(mesh, name, default) # checks hashattr
209 :
210 : Get half-edge attribute list from `mesh` or particular vertex
211 : attribute `name`. The optional `default` argument is returned if
212 : [`hashattr`](@ref) yields `false` similar to `Base.get`.
213 :
214 :
215 : See also [`vattr`](@ref), [`fattr`](@ref), [`eattr`](@ref)
216 : """ hattr
217 :
218 : """
219 : list = eattr(mesh)
220 : attr = eattr(mesh, name)
221 : attr = eattr(mesh, Val(name)) # fast & type-safe if name is a literal
222 : attr = eattr(mesh, attr) # identity
223 : attr = eattr(mesh, name, default) # checks haseattr
224 :
225 : Get edge attribute list from `mesh` or particular vertex attribute
226 : `name`. The optional `default` argument is returned if
227 : [`haseattr`](@ref) yields `false` similar to `Base.get`.
228 :
229 :
230 : See also [`vattr`](@ref), [`fattr`](@ref), [`hattr`](@ref)
231 : """ eattr
232 :
233 4 : hasvattr(mesh::Mesh, name::Symbol) = hasattr(attrs(vattr(mesh)), name)
234 :
235 2 : hasvattr(mesh::Mesh, ::Val{S}) where {S} = hasvattr(mesh, S)
236 :
237 0 : hasvattr(::Mesh, ::Nothing) = false
238 :
239 0 : hasvattr(::Mesh, a::Attribute{T, VHnd}) where {T} = true
240 :
241 : """
242 : hasvattr(mesh, name)
243 :
244 : hasvattr(mesh, :name)
245 : hasvattr(mesh, Val(:name))
246 :
247 : hasvattr(mesh, nothing) # always false
248 : hasvattr(mesh, ::Attribute{T, FHnd}) # always true
249 :
250 : Does `mesh` provide vertex attribute `name`?
251 :
252 : !!! note
253 : Calling `hasvattr` with a vertex attribute yields always `true`
254 : for consistency with passing attributes.
255 : There is no name we could check!
256 :
257 : See also [`vattr`](@ref)
258 : """
259 : hasvattr
260 :
261 :
262 3 : hasfattr(mesh::Mesh, name::Symbol) = hasattr(attrs(fattr(mesh)), name)
263 :
264 1 : hasfattr(mesh::Mesh, _name::Val{S}) where {S} = hasfattr(mesh, S)
265 :
266 0 : hasfattr(::Mesh, ::Nothing) = false
267 :
268 0 : hasfattr(::Mesh, a::Attribute{T, FHnd}) where {T} = true
269 :
270 : """
271 : hasfattr(mesh, name)
272 :
273 : hasfattr(mesh, :name)
274 : hasfattr(mesh, Val(:name))
275 : hasfattr(mesh, nothing) # always false
276 : hasfattr(mesh, ::Attribute{T, FHnd}) # always true
277 :
278 : Does `mesh` provide face attribute `name`?
279 :
280 : !!! note
281 : Calling `hasfattr` with a face attribute yields always `true`
282 : for consistency with passing attributes.
283 : There is no name we could check!
284 :
285 : See also [`fattr`](@ref)
286 : """
287 : hasfattr
288 :
289 :
290 3 : hashattr(mesh::Mesh, name::Symbol) = hasattr(attrs(hattr(mesh)), name)
291 :
292 1 : hashattr(mesh::Mesh, _name::Val{S}) where {S} = hashattr(mesh, S)
293 :
294 0 : hashattr(::Mesh, ::Nothing) = false
295 :
296 0 : hashattr(::Mesh, a::Attribute{T, HHnd}) where {T} = true
297 :
298 : """
299 : hashattr(mesh, name)
300 :
301 : hashattr(mesh, :name)
302 : hashattr(mesh, Val(:name))
303 : hashattr(mesh, nothing) # always false
304 : hashattr(mesh, ::Attribute{T, HHnd}) # always true
305 :
306 :
307 : Does `mesh` provide half-edge attribute `name`?
308 :
309 : !!! note
310 : Calling `hashattr` with an half-edge attribute yields always `true`
311 : for consistency with passing attributes.
312 : There is no name we could check!
313 :
314 : See also [`hattr`](@ref)
315 : """ hashattr
316 :
317 3 : haseattr(mesh::Mesh, name::Symbol) = hasattr(attrs(eattr(mesh)), name)
318 :
319 1 : haseattr(mesh::Mesh, _name::Val{S}) where {S} = haseattr(mesh, S)
320 :
321 0 : haseattr(::Mesh, ::Nothing) = false
322 :
323 0 : haseattr(::Mesh, a::Attribute{T, EHnd}) where {T} = true
324 :
325 : """
326 : haseattr(mesh, name)
327 :
328 : haseattr(mesh, :name)
329 : haseattr(mesh, Val(:name))
330 : haseattr(mesh, nothing) # always false
331 : haseattr(mesh, ::Attribute{T, EHnd}) # always true
332 :
333 :
334 : Does `mesh` provide edge attribute `name`?
335 :
336 : !!! note
337 : Calling `haseattr` with an edge attribute yields always `true`
338 : for consistency with passing attributes.
339 : There is no name we could check!
340 :
341 : See also [`eattr`](@ref)
342 : """ haseattr
343 :
344 :
345 : """
346 : values = collect(mesh, vattr(...))
347 :
348 : Collect all used values.
349 :
350 : !!! note
351 : `vec(vattr(...))` provides a view that includes unused values.
352 : """
353 0 : Base.collect(mesh::Mesh, va::Attribute{T, VHnd}) where {T} =
354 : T[va[v] for v in vertices(mesh)]
355 :
356 : """
357 : values = collect(mesh, fattr(...))
358 :
359 : Collect all used values.
360 :
361 : !!! note
362 : `vec(fattr(...))` provides a view that includes unused values.
363 : """
364 :
365 0 : Base.collect(mesh::Mesh, fa::Attribute{T, FHnd}) where {T} =
366 : T[fa[f] for f in faces(mesh)]
367 :
368 : """
369 : values = collect(mesh, hattr(...))
370 :
371 : Collect all used values.
372 :
373 : !!! note
374 : `vec(hattr(...))` provides a view that includes unused values.
375 : """
376 0 : Base.collect(mesh::Mesh, ha::Attribute{T, HHnd}) where {T} =
377 : T[ha[h] for h in halfedges(mesh)]
378 :
379 : """
380 : values = collect(mesh, ettr(...))
381 :
382 : Collect all used values.
383 :
384 : !!! note
385 : `vec(eattr(...))` provides a view that includes unused values.
386 : """
387 0 : Base.collect(mesh::Mesh, ea::Attribute{T, EHnd}) where {T} =
388 : T[ea[e] for e in edges(mesh)]
389 :
390 : """
391 : Map handles to elements in attribute
392 :
393 : See also [`maphandles`](@ref)
394 : """
395 : struct MapHandles{T, H}
396 80876 : attr::PMeshAttributes.Attribute{T, H}
397 : end
398 :
399 81325 : (ma::MapHandles{T, H})(h::H) where {T, H} = ma.attr[h] :: T
400 :
401 : """
402 : a = vattr(mesh, x)
403 : f = maphandles(a)
404 :
405 : elt = f(v::VHnd)
406 :
407 : Create a functor that maps handles to attribute `a` (e.g., `VHnd` to
408 : vertex attributes) to values.
409 : """
410 80876 : maphandles(attr::PMeshAttributes.Attribute{T, Hnd{S}}) where {T, S} =
411 : MapHandles{T, Hnd{S}}(attr)
|