|
50 | 50 | Face(::Type{<:NgonFace{N}}, ::Type{T}) where {N,T} = NgonFace{N,T}
|
51 | 51 | Face(F::Type{NgonFace{N,FT}}, ::Type{T}) where {FT,N,T} = F
|
52 | 52 |
|
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}} |
57 | 55 |
|
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 |
59 | 65 |
|
60 | 66 | @propagate_inbounds Base.getindex(x::Polytope, i::Integer) = coordinates(x)[i]
|
61 | 67 | @propagate_inbounds Base.iterate(x::Polytope) = iterate(coordinates(x))
|
@@ -295,11 +301,54 @@ abstract type AbstractMesh{Dim, T} <: AbstractGeometry{Dim, T} end
|
295 | 301 | Mesh <: AbstractMesh{Element}
|
296 | 302 | The concrete AbstractMesh type.
|
297 | 303 | """
|
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 |
301 | 351 | end
|
302 |
| -coordinates(mesh::Mesh) = mesh.vertices |
303 | 352 | faces(mesh::Mesh) = mesh.connectivity
|
304 | 353 | Base.getindex(mesh::Mesh, i::Integer) = mesh.vertices[mesh.connectivity[i]]
|
305 | 354 | Base.length(mesh::Mesh) = length(mesh.connectivity)
|
|
0 commit comments