@@ -103,39 +103,98 @@ void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
103
103
if (_graph [node -> id ()].size () == 0 )
104
104
return ;
105
105
106
+ // check if a node is on a given block boundary
107
+ auto is_node_on_block_boundary = [& block_boundary_map ](dof_id_type node_id , const std ::pair < subdomain_id_type , subdomain_id_type > & block_boundary )
108
+ {
109
+ const auto it = block_boundary_map .find (node_id );
110
+ if (it == block_boundary_map .end ())
111
+ return false;
112
+ return it -> second .count (block_boundary ) > 0 ;
113
+ };
114
+
115
+ // check if a series of vectors is collinear/coplanar
116
+ RealVectorValue base ;
117
+ std ::size_t n_edges = 0 ;
118
+ auto has_zero_curvature = [this , & node , & base , & n_edges ](dof_id_type connected_id ) {
119
+ const auto connected_node = _mesh .point (connected_id );
120
+ const RealVectorValue vec = connected_node - * node ;
121
+ // if any connected edge has length zero we give up and don't move the node
122
+ if (vec .norm_sq () < libMesh ::TOLERANCE )
123
+ return false;
124
+
125
+ // count edges
126
+ n_edges ++ ;
127
+
128
+ // store first two edges for later projection
129
+ if (n_edges == 1 ) {
130
+ base = vec ;
131
+ return true;
132
+ }
133
+
134
+ // 2D - collinear - check cross product of first edge with all other edges
135
+ if (_mesh .mesh_dimension () == 2 )
136
+ return (base .cross (vec ).norm_sq () < libMesh ::TOLERANCE );
137
+
138
+ // 3D
139
+ if (n_edges == 2 ) {
140
+ const auto cross = base .cross (vec );
141
+ if (cross .norm_sq () < libMesh ::TOLERANCE )
142
+ n_edges -- ;
143
+ else
144
+ base = cross ;
145
+ return true;
146
+ }
147
+
148
+ return (base * vec < libMesh ::TOLERANCE );
149
+ };
150
+
106
151
if (on_boundary .count (node -> id ()))
107
152
{
108
153
// project to boundary
154
+ for (const auto & connected_id : _graph [node -> id ()])
155
+ if (on_boundary .count (connected_id ) && !has_zero_curvature (connected_id ))
156
+ return ;
157
+ // we have not failed the curvature check, but do we have enough edges?
158
+ if (n_edges < _mesh .mesh_dimension ())
159
+ return ;
160
+
161
+ // now project
162
+ // base /= base.norm();
163
+ // auto delta = new_positions[node->id()] - *node;
164
+ // if (_mesh.mesh_dimension() == 2)
165
+ // delta = base * (delta * base);
166
+ // else
167
+ // delta -= base * (delta * base);
168
+ // *node += delta;
109
169
return ;
110
170
}
111
171
112
- // check if a node is on a given block boundary
113
- auto is_node_on_block_boundary = [ & block_boundary_map ]( dof_id_type node_id , const std :: pair < subdomain_id_type , subdomain_id_type > & block_boundary )
172
+ const auto it = block_boundary_map . find ( node -> id ());
173
+ if ( it != block_boundary_map . end () )
114
174
{
115
- auto range = block_boundary_map .equal_range (node_id );
116
- for (auto i = range .first ; i != range .second ; ++ i )
117
- if (i -> second == block_boundary )
118
- return true;
119
- return false;
120
- };
175
+ const auto num_boundaries = it -> second .size ();
121
176
122
- const auto range = block_boundary_map .equal_range (node -> id ());
123
- const auto num_boundaries = std ::distance (range .first , range .second );
177
+ // do not touch nodes at the intersection of two or more boundaries
178
+ if (num_boundaries > 1 )
179
+ return ;
124
180
125
- // do not touch nodes at the intersection of two or more boundaries
126
- if (num_boundaries > 1 )
127
- return ;
181
+ if (num_boundaries == 1 )
182
+ {
183
+ // project to block boundary
184
+ const auto & boundary = * (it -> second .begin ());
185
+ // iterate over neighboring nodes that share the same boundary and check if all edges are coplanar/collinear
186
+ for (const auto & connected_id : _graph [node -> id ()])
187
+ if (is_node_on_block_boundary (connected_id , boundary ) && !has_zero_curvature (connected_id ))
188
+ return ;
189
+ // we have not failed the curvature check, but do we have enough edges?
190
+ if (n_edges < _mesh .mesh_dimension ())
191
+ return ;
128
192
129
- if (num_boundaries == 1 )
130
- {
131
- // project to block boundary
132
- const auto & boundary = range .first -> second ;
133
- // iterate over neighboring nodes that share the same boundary and check if all edges are coplanar/collinear
134
- for (const auto & connected_id : _graph [node -> id ()])
135
- if (is_node_on_block_boundary (connected_id , boundary ))
136
- continue ;
193
+ // now project
194
+ // if (_mesh.mesh_dimension() == 2)
137
195
138
- return ;
196
+ return ;
197
+ }
139
198
}
140
199
141
200
// otherwise just move the node freely
0 commit comments