Line data Source code
1 1 : triangletable(mesh::Mesh) = triangletable(mesh, faces(mesh))
2 :
3 1 : triangletable(mesh::Mesh, faces) =
4 : [ SVector{3, Int}(triangle(mesh, FHnd(f))) for f in faces ]
5 :
6 : """
7 : triples = triangletable(mesh[, faces])
8 :
9 : Generate table of triangles for `mesh`: `triples` is a
10 : `Vector{SVector{3, Int}}`, where each element `triples[i]` contains
11 : the vertex indices of the `i`-th triangle.
12 :
13 : The optional argument `faces` restricts and/or permutes the sequence
14 : of faces.
15 :
16 : !!! warning "Precondition"
17 : This method **requires a triangle mesh**!
18 :
19 : See also [`facetable`](@ref), [`compacttriangletable`](@ref)
20 : """ triangletable
21 :
22 : """
23 : triples, vmap = compacttriangletable(mesh)
24 :
25 : Similar to [`triangletable`](@ref) but generate contiguous vertex
26 : indices (of the used vertices). The effect is similar to first calling
27 : [`compact`](@ref) but this method is more efficient.
28 :
29 : In contrast to [`triangletable`](@ref), this method returns also a
30 : mapping `vmap::Vector{VHnd}` from contiguous indices to vertex handles.
31 :
32 : See also [`triangletable`](@ref), [`compactfacetable`](@ref)
33 : """
34 2 : function compacttriangletable(mesh::Mesh)
35 4 : vmap = Vector{VHnd}(undef, nv(mesh))
36 12 : ivmap = zeros(Int, n_total(vattr(mesh)))
37 :
38 4 : for (i, v) in enumerate(vertices(mesh))
39 11 : vmap[i] = v
40 11 : ivmap[Int(v)] = i
41 20 : end
42 :
43 6 : function triple(f)
44 16 : SVector{3, Int}(map(v -> ivmap[Int(v)], triangle(mesh, f)))
45 : end
46 :
47 2 : [ triple(f) for f in faces(mesh) ], vmap
48 : end
49 :
50 3 : facetable(n::Val{N}, mesh::Mesh) where {N} = facetable(n, mesh, faces(mesh))
51 :
52 3 : function facetable(n::Val{N}, mesh::Mesh, faces) where {N}
53 3 : [ _makeface!(n, face(mesh, FHnd(f))) for f in faces ]
54 : end
55 :
56 7 : function _makeface!(::Val{N}, face) where {N}
57 7 : n = length(face)
58 7 : if n > N
59 0 : @warn "facetable: degree $(n) exceeds maximum $(N)"
60 0 : return zeros(SVector{N, Int})
61 7 : elseif n < N
62 2 : for _ in n+1:N
63 2 : push!(face, NoV)
64 2 : end
65 : end
66 :
67 7 : SVector{N, Int}(face)
68 : end
69 :
70 : """
71 : fs = facetable(::Val(n), mesh[, faces])
72 :
73 : Generalized [`triangletable`](@ref) that converts `mesh` with maximum
74 : face [`degree`](@ref) `n` info `Vector{SVector{n, Int}}`. Faces with
75 : degree `<n` have `n - degree` *trailing zero* indices.
76 :
77 : !!! note
78 : Faces with degree `>n` are ignored with a warning message.
79 :
80 : !!! note
81 : This function is significantly less efficient than
82 : [`triangletable`](@ref)
83 :
84 : See also [`triangletable`](@ref)
85 : """ facetable
86 :
87 : """
88 : fs, vmap = compactfacetable(mesh)
89 :
90 : Similar to [`facetable`](@ref) but generate contiguous vertex
91 : indices (of the used vertices). The effect is similar to first calling
92 : [`compact`](@ref) but this method is more efficient.
93 :
94 : In contrast to [`facetable`](@ref), this method returns also a
95 : mapping `vmap::Vector{VHnd}` from contiguous indices to vertex handles.
96 :
97 : See also [`facetable`](@ref), [`compacttriangletable`](@ref)
98 : """
99 1 : function compactfacetable(n::Val{N}, mesh::Mesh) where {N}
100 2 : vmap = Vector{VHnd}(undef, nv(mesh))
101 6 : ivmap = zeros(Int, n_total(vattr(mesh)))
102 :
103 2 : for (i, v) in enumerate(vertices(mesh))
104 5 : vmap[i] = v
105 5 : ivmap[Int(v)] = i
106 9 : end
107 :
108 9 : mapface(f) = map(v -> ivmap[Int(v)], f)
109 :
110 1 : [ mapface(_makeface!(n, face(mesh, FHnd(f)))) for f in faces(mesh) ], vmap
111 : end
112 :
113 : #-----------------------------------------------------------------------------
114 :
115 : """
116 : mesh = createmesh(faces, template::Mesh, nv::Int = 0)
117 : mesh = createmesh(faces::Matrix, template::Mesh, nv::Int = 0)
118 :
119 : Create `mesh` from index table `faces` and `template` that
120 : defines attributes. The optional `nv` specifies the minimum number of
121 : vertices that may be larger than the maximum index in `triangles`.
122 :
123 : `faces` enumerates each face as a sequence of vertex handles or
124 : indices. Before passing `VHnd` to [`addface!`](@ref), any invalid
125 : indices are removed.
126 :
127 : If `faces` is a `Matrix`, indices for each face are defined my
128 : matrix columns.
129 :
130 : !!! note
131 : Typically, `faces` is a `Vector` of triangles, e.g.,
132 : `NTuple{3, Int}` or `SVector{3, Int}`.
133 :
134 : You can use `NTuple{4, Int}` or `SVector{4, Int}` and "switch"
135 : between triangles and quads by providing an invalid index
136 : (e.g., zero or `NoV`) as fourth vertex.
137 :
138 : See also [`triangletable`](@ref), [`addface!`](@ref)
139 : """
140 33 : function createmesh(faces, template::Mesh{V, F, H, E},
141 : nv::Int = 0) where {V, F, H, E}
142 33 : mesh = similar(template)
143 17 : nv = max(nv, maximum(maximum.(faces)))
144 17 : sizehint!(mesh, nv, length(faces))
145 :
146 17 : addvertices!(mesh, nv)
147 :
148 33 : for f in _enumeratefaces(faces)
149 9586 : addface!(mesh, filter(isindex, VHnd.(f))...) # TODO: avoid dynamic dispatch (collect & special case: triangulation)
150 19154 : end
151 :
152 17 : mesh :: Mesh{V, F, H, E}
153 : end
154 :
155 1 : _enumeratefaces(faces) = faces
156 16 : _enumeratefaces(faces::AbstractMatrix) = eachcol(faces)
|