@@ -103,39 +103,98 @@ void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
103103 if (_graph [node -> id ()].size () == 0 )
104104 return ;
105105
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+
106151 if (on_boundary .count (node -> id ()))
107152 {
108153 // 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;
109169 return ;
110170 }
111171
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 () )
114174 {
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 ();
121176
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 ;
124180
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 ;
128192
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)
137195
138- return ;
196+ return ;
197+ }
139198 }
140199
141200 // otherwise just move the node freely
0 commit comments