Skip to content

Commit ff64179

Browse files
committed
update Mesh & MultiFace types
1 parent 5632303 commit ff64179

File tree

1 file changed

+58
-9
lines changed

1 file changed

+58
-9
lines changed

src/basic_types.jl

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,18 @@ end
5050
Face(::Type{<:NgonFace{N}}, ::Type{T}) where {N,T} = NgonFace{N,T}
5151
Face(F::Type{NgonFace{N,FT}}, ::Type{T}) where {FT,N,T} = F
5252

53-
struct MultiFace{N, T, FaceType <: AbstractFace{N, T}, Names, M}
54-
pos_face::FaceType
55-
attrib_faces::NamedTuple{Names, NTuple{M, FaceType}}
56-
end
53+
struct MultiFace{N, T, FaceType <: AbstractFace{N, T}, Names, M} <: AbstractFace{N, T}
54+
faces::NamedTuple{Names, NTuple{M, FaceType}}
5755

58-
MultiFace(face::AbstractFace; kwargs...) = MultiFace(face, NamedTuple(kwargs))
56+
function MultiFace(nt::NamedTuple{Names, NTuple{M, FT}}) where {N, T, FT <: AbstractFace{N, T}, Names, M}
57+
if FT <: MultiFace
58+
error("A MultiFace cannot contain MultiFaces.")
59+
end
60+
61+
return new{N, T, FT, Names, M}(nt)
62+
end
63+
end
64+
Base.names(::Type{<: MultiFace{N, T, FT, Names}}) where {N, T, FT, Names} = Names
5965

6066
@propagate_inbounds Base.getindex(x::Polytope, i::Integer) = coordinates(x)[i]
6167
@propagate_inbounds Base.iterate(x::Polytope) = iterate(coordinates(x))
@@ -295,11 +301,54 @@ abstract type AbstractMesh{Dim, T} <: AbstractGeometry{Dim, T} end
295301
Mesh <: AbstractMesh{Element}
296302
The concrete AbstractMesh type.
297303
"""
298-
struct Mesh{Dim, T<:Number, V<:AbstractVector{Point{Dim, T}}, C <: AbstractVector{<: AbstractFace}} <: AbstractMesh{Dim, T}
299-
vertices::V
300-
connectivity::C
304+
struct Mesh{
305+
Dim, T <: Real, # TODO: Number?
306+
FaceType <: AbstractFace,
307+
Names,
308+
VertexAttribTypes <: Tuple{AbstractVector{Point{Dim, T}}, Vararg{AbstractVector}},
309+
FaceVecType <: AbstractVector{FaceType}
310+
} <: AbstractMesh{Dim, T}
311+
312+
vertex_attributes::NamedTuple{Names, VertexAttribTypes}
313+
connectivity::FaceVecType
314+
views::Vector{UnitRange}
315+
316+
function Mesh(
317+
va::NamedTuple{Names, VAT},
318+
f::FVT,
319+
views::Vector{UnitRange} = UnitRange[]
320+
) where {
321+
D, T, FT, Names,
322+
VAT <: Tuple{AbstractVector{Point{D, T}}, Vararg{AbstractVector}},
323+
FVT <: AbstractVector{FT}
324+
}
325+
326+
# verify type
327+
if first(Names) !== :position
328+
error("The first vertex attribute should be a 'position' but is a '$(first(Names))'.")
329+
end
330+
331+
if FT <: MultiFace
332+
f_names = names(FT)
333+
if Names != f_names
334+
error(
335+
"Cannot construct a mesh with vertex attribute names $Names and MultiFace " *
336+
"attribute names $f_names. These must include the same names in the same order."
337+
)
338+
end
339+
elseif MultiFace <: FT
340+
# TODO: This is supposed to catch mixed types like
341+
# [MultiFace(position = f1, normal = f2), MultiFace(position = f3)]
342+
# but really just catches AbstractFace{N, T}[]. Technically we can
343+
# probably handle mixtures of MultiFace and other Face types, but do
344+
# we want to bother? Also do we want to allow mixtures of e.g.
345+
# TriangleFace and QuadFace?
346+
error("Face vectors that may include `MultiFace`s with different names are not allowed. (Type $FT too abstract.)")
347+
end
348+
349+
return new{D, T, FT, Names, VAT, FVT}(va, f, views)
350+
end
301351
end
302-
coordinates(mesh::Mesh) = mesh.vertices
303352
faces(mesh::Mesh) = mesh.connectivity
304353
Base.getindex(mesh::Mesh, i::Integer) = mesh.vertices[mesh.connectivity[i]]
305354
Base.length(mesh::Mesh) = length(mesh.connectivity)

0 commit comments

Comments
 (0)