Line data Source code
1 : abstract type AbstractStdGeometry{Tri} <: AbstractGeometry end
2 :
3 : # TODO: make below a "public interface"?!?
4 :
5 259033 : _mesh(g::AbstractStdGeometry) = g.mesh
6 501621 : _vpos(g::AbstractStdGeometry) = g.x
7 468022 : _fnrm(g::AbstractStdGeometry) = g.fnrm
8 96820 : _vnrm(g::AbstractStdGeometry) = g.vnrm
9 :
10 : struct GeometryVx{T, Tri, V, F, H, E} <: AbstractStdGeometry{Tri}
11 70 : mesh::Mesh{V, F, H, E}
12 : x::Attribute{T, VHnd}
13 : end
14 :
15 : struct GeometryVxFn{T, Tri, V, F, H, E} <: AbstractStdGeometry{Tri}
16 4 : mesh::Mesh{V, F, H, E}
17 : x::Attribute{T, VHnd}
18 : fnrm::Attribute{T, FHnd}
19 : end
20 :
21 : struct GeometryVxVn{T, Tri, V, F, H, E} <: AbstractStdGeometry{Tri}
22 : mesh::Mesh{V, F, H, E}
23 : x::Attribute{T, VHnd}
24 : vnrm::Attribute{T, VHnd}
25 : end
26 :
27 : struct GeometryVxFnVn{T, Tri, V, F, H, E} <: AbstractStdGeometry{Tri}
28 2 : mesh::Mesh{V, F, H, E}
29 : x::Attribute{T, VHnd}
30 : fnrm::Attribute{T, FHnd}
31 : vnrm::Attribute{T, VHnd}
32 : end
33 :
34 62 : function geometry(mesh::Mesh{V, F, H, E}, x) where {V, F, H, E}
35 62 : ax = vattr(mesh, x)
36 62 : GeometryVx{eltype(ax), NoTriangulation(), V, F, H, E}(mesh, ax)
37 : end
38 :
39 2 : function geometry(mesh::Mesh{V, F, H, E}, x, fnormal) where {V, F, H, E}
40 2 : ax = vattr(mesh, x)
41 2 : GeometryVxFn{eltype(ax), NoTriangulation(), V, F, H, E}(mesh, ax,
42 : fattr(mesh, fnormal))
43 : end
44 :
45 1 : function geometry(mesh::Mesh{V, F, H, E}, x,
46 : fnormal, vnormal) where {V, F, H, E}
47 1 : ax = vattr(mesh, x)
48 1 : GeometryVxFnVn{eltype(ax), NoTriangulation(), V, F, H, E}(mesh, ax,
49 : fattr(mesh, fnormal), vattr(mesh, vnormal))
50 : end
51 :
52 0 : function geometry(mesh::Mesh{V, F, H, E}, x,
53 : ::Nothing, vnormal) where {V, F, H, E}
54 0 : ax = vattr(mesh, x)
55 0 : GeometryVxVn{eltype(ax), NoTriangulation(), V, F, H, E}(mesh, ax,
56 : vattr(mesh, vnormal))
57 : end
58 :
59 0 : geometry(mesh::Mesh, args::NamedTuple) =
60 : _CHECK_NAMED_TUPLE_FIELDS(mesh, args)
61 :
62 44 : geometry(mesh::Mesh, args::NamedTuple{(:position,)}) =
63 : geometry(mesh, args.position)
64 :
65 2 : geometry(mesh::Mesh, args::NamedTuple{(:position, :fnormal)}) =
66 : geometry(mesh, args.position, args.fnormal)
67 :
68 0 : geometry(mesh::Mesh, args::NamedTuple{(:position, :vnormal)}) =
69 : geometry(mesh, args.position, nothing, args.vnormal)
70 :
71 0 : geometry(mesh::Mesh, x, args::NamedTuple{(:fnormal,)}) =
72 : geometry(mesh, x, args.fnormal)
73 :
74 0 : geometry(mesh::Mesh, x, args::NamedTuple{(:vnormal,)}) =
75 : geometry(mesh, x, nothing, args.vnormal)
76 :
77 1 : geometry(mesh::Mesh, args::NamedTuple{(:position, :fnormal, :vnormal)}) =
78 : geometry(mesh, args.position, args.fnormal, args.vnormal)
79 :
80 0 : geometry(mesh::Mesh, args::NamedTuple{(:position, :vnormal, :fnormal)}) =
81 : geometry(mesh, args.position, args.fnormal, args.vnormal)
82 :
83 0 : geometry(mesh::Mesh, x, args::NamedTuple{(:fnormal,:vnormal)}) =
84 : geometry(mesh, x, args.fnormal, args.vnormal)
85 :
86 0 : geometry(mesh::Mesh, x, args::NamedTuple{(:vnormal,:fnormal)}) =
87 : geometry(mesh, x, args.fnormal, args.vnormal)
88 :
89 84 : geometry(mesh::Mesh; kargs...) = geometry(mesh, NamedTuple(kargs))
90 :
91 : # NOTE: require dispatch on given "keyword arguments" for type stability
92 :
93 : """
94 : g = geometry(mesh, x[, fnrm, vnrm])
95 : g = geometry(mesh, x[, fnormal=fnrm, vnormal=nvrm])
96 : g = geometry(mesh, x, nothing, vnormal=nvrm]
97 : g = geometry(mesh, position=x[, fnormal=fnrm, vnormal=nvrm])
98 :
99 : Bind `mesh` in an [`AbstractGeometry`](@ref) instance that provides
100 : attributes with vertex positions and optionally face normals and
101 : vertex normals. `x`, `fnrm`, and `vnrm` denote attributes of the mesh.
102 :
103 : Use the returned `g` for computing geometric quantities which can be
104 : stored in and queried from attributes if available.
105 :
106 : Here is a typical pattern: [`facenormal`](@ref) *computes* a normal
107 : vector, [`normal`](@ref) queries a normal vector if an attribute is
108 : available, otherwise falls back to computing `facenormal`. Finally,
109 : [`updatenormal!`](@ref) stores a computed normal in an attribute if
110 : available (no effect else).
111 :
112 : !!! tip
113 : You can pass attributes (inexpensive) or attribute names.
114 : The latter is efficient and type-stable if you provide *types*
115 : such as `Val(:x)` (instead of `:x`), see also
116 : [Access and performance](@ref)
117 :
118 : !!! note
119 : 1. `geometry` always requires vertex positions. You can but
120 : don't have to provide face normals and/or vertex normals.
121 : 2. Providing or not providingg an attribute effects the use
122 : of stored data versus computing data on demand.
123 :
124 : !!! warning
125 : The current implememtation requires the same element types
126 : for positions and normals, e.g., `SVector{3, Float64}`.
127 :
128 : See also [`triangulated`](@ref)
129 : """ geometry
130 :
131 8 : triangulated(g::GeometryVx{T, NoTriangulation(), V, F, H, E}) where {T, V, F,H, E} =
132 : GeometryVx{T, IsTriangulation(), V, F, H, E}(g.mesh, g.x)
133 :
134 2 : triangulated(g::GeometryVxFn{T, NoTriangulation(), V, F, H, E}) where {T, V, F,H, E} =
135 : GeometryVxFn{T, IsTriangulation(), V, F, H, E}(g.mesh, g.x, g.fnrm)
136 :
137 0 : triangulated(g::GeometryVxVn{T, NoTriangulation(), V, F, H, E}) where {T, V, F,H, E} =
138 : GeometryVxVn{T, IsTriangulation(), V, F, H, E}(g.mesh, g.x, nothing, g.vnrm)
139 :
140 1 : triangulated(g::GeometryVxFnVn{T, NoTriangulation(), V, F, H, E}) where {T, V, F,H, E} =
141 : GeometryVxFnVn{T, IsTriangulation(), V, F, H, E}(g.mesh, g.x, g.fnrm, g.vnrm)
142 :
143 : """
144 : g = triangulated(geometry(mesh, ...))
145 :
146 : Tags `g` as a triagulated surface, i.e., all faces of `mesh` are
147 : assumed to be triangles. For instance, calling [`facearea`](@ref)
148 : becomes equivalent to calling [`trianglearea`](@ref).
149 :
150 : !!! warning "precondition"
151 : Requires that `mesh` is *and remains* a triangle mesh.
152 : This is a contract with the user, which is *not checked*!
153 :
154 : See also [`geometry`](@ref)
155 : """ triangulated
156 :
157 16692 : _has_vx(::GeometryVx) = HasVX()
158 97143 : _has_fn(::GeometryVx) = NoFN()
159 16148 : _has_vn(::GeometryVx) = NoVN()
160 :
161 16140 : _has_vx(::GeometryVxFn) = HasVX()
162 258355 : _has_fn(::GeometryVxFn) = HasFN()
163 16148 : _has_vn(::GeometryVxFn) = NoVN()
164 :
165 0 : _has_vx(::GeometryVxVn) = HasVX()
166 0 : _has_fn(::GeometryVxVn) = NoFN()
167 0 : _has_vn(::GeometryVxVn) = HasVN()
168 :
169 112904 : _has_vx(::GeometryVxFnVn) = HasVX()
170 209684 : _has_fn(::GeometryVxFnVn) = HasFN()
171 96828 : _has_vn(::GeometryVxFnVn) = HasVN()
172 :
173 49040 : _istriangulation(::AbstractStdGeometry{Tri}) where {Tri} = Tri
174 :
175 0 : function Base.show(io::IO, g::AbstractGeometry)
176 0 : traits = String[]
177 0 : istriangulation(g) && push!(traits, "Δ")
178 0 : has_position(g) && push!(traits, "x")
179 0 : has_fnormal(g) && push!(traits, "fn")
180 0 : has_vnormal(g) && push!(traits, "vn")
181 :
182 0 : print(io, "Geometry[", join(traits, ","), "]")
183 : end
|