Line data Source code
1 2 : Base.angle(g::AbstractGeometry, h::HHnd) =
2 : anglenext(g::AbstractGeometry, h::HHnd)
3 :
4 1 : Base.angle(mesh::Mesh, x, h::HHnd) =
5 : Base.angle(geometry(mesh, position=x), h)
6 :
7 : """
8 : g = geometry(mesh, position=x)
9 :
10 : α = angle(g, h::Hnd)
11 : α = angle(mesh, x, h::Hnd)
12 :
13 : Synonym for [`anglenext`](@ref).
14 :
15 : See also [`anglenext`](@ref), [`angleprev`](@ref)
16 : """ Base.angle
17 :
18 : """
19 : g = geometry(mesh, position=x)
20 :
21 : α = anglenext(g, h::Hnd)
22 : α = anglenext(mesh, x, h::Hnd)
23 :
24 : Compute angle `α` enclosed by half-edge `h` and its successor
25 : `next(mesh, h)` within their common face.
26 :
27 : See also [`angle`](@ref), [`next`](@ref), [`angleprev`](@ref)
28 : """
29 2 : anglenext(g::AbstractGeometry, h::HHnd) =
30 : _angle(g::AbstractGeometry, h, next(tessellation(g), h))
31 :
32 0 : anglenext(mesh::Mesh, x, h::HHnd) =
33 : anglenext(geometry(mesh, position=x), h)
34 :
35 : """
36 : g = geometry(mesh, position=x)
37 :
38 : α = angleprev(g, h::Hnd)
39 : α = angleprev(mesh, x, h::Hnd)
40 :
41 : Compute angle `α` enclosed by half-edge `h` and its predecessor
42 : `pred(mesh, h)` within their common face.
43 :
44 : See also [`prev`](@ref), [`anglenext`](@ref), [`angle`](@ref),
45 : """
46 2 : angleprev(g::AbstractGeometry, h::HHnd) =
47 : _angle(g::AbstractGeometry, prev(tessellation(g), h), h)
48 :
49 1 : angleprev(mesh::Mesh, x, h::HHnd) =
50 : angleprev(geometry(mesh, position=x), h)
51 :
52 4 : function _angle(g::AbstractGeometry, h1::HHnd, h2::HHnd)
53 4 : v1 = edgevector(g, h1)
54 4 : v2 = edgevector(g, h2)
55 :
56 4 : angle(-v1, v2)
57 : end
58 :
59 : """
60 : α = angle(v1, v2)
61 :
62 : Compute angle (rad) enclosed by vectors `v1` and `v2`.
63 :
64 : !!! warn "precondition"
65 : Both vectors `v1, v2` must have positive length.
66 :
67 : """
68 77 : function Base.angle(v1::AbstractVector, v2::AbstractVector)
69 77 : cs = dot(v1, v2) / (norm(v1) * norm(v2))
70 154 : cs = clamp(cs, -one(cs), +one(cs))
71 :
72 77 : acos(cs)
73 : end
74 :
75 73 : function dihedralangle(g::AbstractGeometry, h::Union{HHnd, EHnd})
76 73 : mesh = tessellation(g)
77 219 : f1, f2 = map(h -> face(mesh, h), halfedges(mesh, h))
78 :
79 73 : angle(normal(g, f1), normal(g, f2))
80 : end
81 :
82 37 : dihedralangle(mesh::Mesh, x, h::Union{HHnd, EHnd}) =
83 : dihedralangle(geometry(mesh, position=x), h)
84 :
85 : """
86 : g = geometry(mesh, position=x, ...)
87 :
88 : α = dihedralangle(g, h::HHnd)
89 : α = dihedralangle(g, e::EHnd)
90 :
91 : α = dihedralangle(mesh, x, ...)
92 :
93 : Compute *dihedral angle* enclosed by the faces that share half-edge
94 : `h` (or edge `e`).
95 :
96 : !!! warn "precondition"
97 : `h` and `e` must denote an **inner** (half-)edge, i.e., both faces
98 : are well-defined.
99 :
100 : !!! note
101 : The face normals of `g::AbstractGeometry` are determined by
102 : [`normal`](@ref), i.e., the normal vector is read from the *face
103 : attribute* if present (and computed otherwise).
104 :
105 : See also [`angle`](@ref), [`computedihedralangle`](@ref)
106 : """ dihedralangle
107 :
108 : """
109 : g = geometry(mesh, position=x, ...)
110 :
111 : α = computedihedralangle(g, h::HHnd)
112 : α = computedihedralangle(g, e::EHnd)
113 :
114 : Same as [`dihedralangle`](@ref) but enforce computation of face
115 : normals, i.e., **do not** lookup face attribute if present.
116 :
117 : See also [`dihedralangle`](@ref)
118 : """
119 37 : computedihedralangle(g::AbstractGeometry, h::Union{HHnd, EHnd}) =
120 : dihedralangle(tessellation(g), position(g), h)
|