Line data Source code
1 : """
2 : vcenter = split!(mesh, f::FHnd[, v::VHnd = NoV])
3 :
4 : Split **face** `f` by adding vertex `v` and connecting each of its
5 : edges to `v`. The face `f` remains valid and becomes a triangle, and
6 : `degree(mesh, f)-1` new triangles are created. If `f` is a triangle,
7 : this is a 1:3-split. The method returns the vertex `vcenter` at which
8 : `f` or `e` is split.
9 :
10 : - If `v == NoV`, a new vertex `vcenter` is created.
11 : - If `!isused(mesh, v)`, the vertex `v` is "reused", i.e., `vcenter == v`.
12 : - Otherwise `v` must be an *isolated* vertex, and `vcenter == v`.
13 : """
14 3 : function split!(mesh::Mesh, f::FHnd, v::VHnd = NoV) :: VHnd
15 3 : @massert isused(mesh, f)
16 :
17 3 : isused(mesh, v) || (v = addvertex!(mesh, v))
18 2 : @massert isisolated(mesh, v)
19 :
20 2 : hend = halfedge(mesh, f)
21 2 : h = next(mesh, hend)
22 :
23 2 : hold = _create_edge(mesh, destination(mesh, hend), v)
24 :
25 2 : _setnexthalfedge!(mesh, hend, hold)
26 2 : _setface!(mesh, hold, f)
27 :
28 2 : hold = opposite(mesh, hold)
29 :
30 6 : while h != hend
31 4 : hnext = next(mesh, h)
32 :
33 4 : fnew = _create_face(mesh, h)
34 4 : hnew = _create_edge(mesh, destination(mesh, h), v)
35 :
36 4 : _setnexthalfedge!(mesh, hnew, hold)
37 4 : _setnexthalfedge!(mesh, hold, h)
38 4 : _setnexthalfedge!(mesh, h, hnew)
39 :
40 4 : _setface!(mesh, hnew, fnew)
41 4 : _setface!(mesh, hold, fnew)
42 4 : _setface!(mesh, h, fnew)
43 :
44 4 : hold = opposite(mesh, hnew)
45 4 : h = hnext
46 4 : end
47 :
48 2 : _setnexthalfedge!(mesh, hold, hend)
49 2 : _setnexthalfedge!(mesh, next(mesh, hend), hold)
50 :
51 2 : _setface!(mesh, hold, f)
52 2 : _sethalfedge!(mesh, v, hold)
53 :
54 2 : v
55 : end
56 :
57 : """
58 : hs, vs = split!(mesh, e::EHnd[, v::VHnd = NoV])
59 :
60 : Split **edge** `e` adding vertex `v`.
61 :
62 : !!! warning "Procondition"
63 : This method **requires a triangle mesh**!
64 :
65 : The method returns the new half-edge `hs` and vertex `vs` at which the
66 : edge was split.
67 :
68 : - If `v == NoV`, a new vertex `vs` is created.
69 : - If `!isused(mesh, v)`, the vertex `v` is "reused", i.e., `vs == v`.
70 : - Otherwise `v` must be an *isolated* vertex, and `vs == v`.
71 : """
72 4 : function split!(mesh::Mesh, e::EHnd, v::VHnd = NoV) :: Tuple{HHnd, VHnd}
73 4 : @massert isused(mesh, e)
74 :
75 5 : isused(mesh, v) || (v = addvertex!(mesh, v))
76 3 : @massert isisolated(mesh, v)
77 :
78 3 : h0, o0 = halfedges(mesh, e)
79 :
80 3 : v2 = destination(mesh, o0)
81 :
82 3 : e1 = _create_edge(mesh, v, v2)
83 3 : t1 = opposite(mesh, e1)
84 :
85 3 : f0 = face(mesh, h0)
86 3 : f3 = face(mesh, o0)
87 :
88 3 : _sethalfedge!(mesh, v, h0)
89 3 : _setvertex!(mesh, o0, v)
90 :
91 3 : if f0 != NoF
92 3 : @massert !isboundary(mesh, h0)
93 3 : @massert istriangle(mesh, f0)
94 :
95 3 : h1 = next(mesh, h0)
96 3 : h2 = next(mesh, h1)
97 :
98 3 : v1 = destination(mesh, h1)
99 :
100 3 : e0 = _create_edge(mesh, v, v1)
101 3 : t0 = opposite(mesh, e0)
102 :
103 3 : _sethalfedge!(mesh, f0, h0)
104 3 : f1 = _create_face(mesh, h2)
105 :
106 3 : _setface!(mesh, h1, f0)
107 3 : _setface!(mesh, t0, f0)
108 3 : _setface!(mesh, h0, f0)
109 :
110 3 : _setface!(mesh, h2, f1)
111 3 : _setface!(mesh, t1, f1)
112 3 : _setface!(mesh, e0, f1)
113 :
114 3 : _setnexthalfedge!(mesh, h0, h1)
115 3 : _setnexthalfedge!(mesh, h1, t0)
116 3 : _setnexthalfedge!(mesh, t0, h0)
117 :
118 3 : _setnexthalfedge!(mesh, e0, h2)
119 3 : _setnexthalfedge!(mesh, h2, t1)
120 3 : _setnexthalfedge!(mesh, t1, e0)
121 : else
122 0 : _setnexthalfedge!(mesh, prev(mesh, h0), t1)
123 0 : _setnexthalfedge!(mesh, t1, h0)
124 : # @massert halfedge(mesh, vh) == h0
125 : end
126 :
127 3 : if f3 != NoF
128 1 : @massert !isboundary(mesh, o0)
129 1 : @massert istriangle(mesh, f3)
130 :
131 1 : o1 = next(mesh, o0)
132 1 : o2 = next(mesh, o1)
133 :
134 1 : v3 = destination(mesh, o1)
135 :
136 1 : e2 = _create_edge(mesh, v, v3)
137 1 : t2 = opposite(mesh, e2)
138 :
139 1 : _sethalfedge!(mesh, f3, o0)
140 1 : f2 = _create_face(mesh, o1)
141 :
142 1 : _setface!(mesh, o1, f2)
143 1 : _setface!(mesh, t2, f2)
144 1 : _setface!(mesh, e1, f2)
145 :
146 1 : _setface!(mesh, o2, f3)
147 1 : _setface!(mesh, o0, f3)
148 1 : _setface!(mesh, e2, f3)
149 :
150 1 : _setnexthalfedge!(mesh, e1, o1)
151 1 : _setnexthalfedge!(mesh, o1, t2)
152 1 : _setnexthalfedge!(mesh, t2, e1)
153 :
154 1 : _setnexthalfedge!(mesh, o0, e2)
155 1 : _setnexthalfedge!(mesh, e2, o2)
156 1 : _setnexthalfedge!(mesh, o2, o0)
157 : else
158 2 : _setnexthalfedge!(mesh, e1, next(mesh, o0))
159 2 : _setnexthalfedge!(mesh, o0, e1)
160 2 : _sethalfedge!(mesh, v, e1)
161 : end
162 :
163 3 : (halfedge(mesh, v2) == h0) && _sethalfedge!(mesh, v2, t1)
164 :
165 3 : t1, v
166 : end
167 :
168 : """
169 : hs, vs = split!(mesh, h::HHnd[, v::VHnd = NoV])
170 :
171 : Split [`edge`](@ref) given by `h`, similar to
172 :
173 : split!(mesh, edge(mesh, h), v)
174 :
175 : but return as `hs` the half-edge with the same orientation as
176 : `h`. This makes a difference if `h != first(halfedges(e))`
177 :
178 : See also [`halfedges`](@ref)
179 : """
180 2 : function split!(mesh::Mesh, h::HHnd, v::VHnd = NoV)
181 2 : hs, vs = split!(mesh, edge(mesh, h), v)
182 :
183 1 : isfirsthalfedge(h) && return hs, vs
184 :
185 0 : opposite(hs), vs
186 : end
|