@@ -157,6 +157,83 @@ std::vector<int> verifyDelaunayTetrahedralization( const SimplicialComplex& mesh
157157 return failed_tetrahedra;
158158}
159159
160+ std::vector<double > computeEquallySpacedLevelSetValues ( const topology::TetMeshCombinatorialMap& mesh,
161+ const Eigen::VectorXd& vertex_values,
162+ const double max_spacing )
163+ {
164+ // 1. Compute gradient magnitude for each triangle (constant per triangle)
165+ std::vector<double > gradient_magnitudes;
166+ std::vector<std::pair<double , double >> triangle_value_ranges;
167+
168+ const topology::CombinatorialMapBoundary bdry ( mesh );
169+
170+ const auto vert_ids = indexingOrError ( bdry, 0 );
171+
172+ iterateCellsWhile ( bdry, 2 , [&]( const topology::Face& face ) {
173+ const auto tri = triangleOfFace ( mesh, face );
174+
175+ const double f0 = vertex_values ( vert_ids ( topology::Vertex ( face.dart () ) ) );
176+ const double f1 = vertex_values ( vert_ids ( topology::Vertex ( phi ( bdry, 1 , face.dart () ).value () ) ) );
177+ const double f2 = vertex_values ( vert_ids ( topology::Vertex ( phi ( bdry, -1 , face.dart () ).value () ) ) );
178+
179+ const Eigen::Vector3d field_vals ( f0, f1, f2 );
180+ const Eigen::Vector3d grad = gradient ( tri, field_vals );
181+ const double grad_magnitude = grad.norm ();
182+
183+ if ( grad_magnitude < 1e-12 ) return true ; // Skip degenerate/flat triangles
184+
185+ gradient_magnitudes.push_back ( grad_magnitude );
186+
187+ const double f_min = std::min ( { f0, f1, f2 } );
188+ const double f_max = std::max ( { f0, f1, f2 } );
189+ triangle_value_ranges.push_back ( { f_min, f_max } );
190+ return true ;
191+ } );
192+
193+ // 2. Step through [0,1], at each step finding the minimum gradient
194+ // in the "active" triangles (those intersected by current level set)
195+ std::vector<double > levels = { 0.0 };
196+ double current_value = 0.0 ;
197+
198+ while ( current_value < 1.0 - 1e-10 )
199+ {
200+ // Find min gradient among triangles that contain current_value
201+ double min_grad = std::numeric_limits<double >::infinity ();
202+ for ( size_t i = 0 ; i < gradient_magnitudes.size (); ++i )
203+ {
204+ if ( triangle_value_ranges.at ( i ).first <= current_value &&
205+ current_value <= triangle_value_ranges.at ( i ).second )
206+ {
207+ min_grad = std::min ( min_grad, gradient_magnitudes.at ( i ) );
208+ }
209+ }
210+
211+ if ( std::isinf ( min_grad ) || min_grad < 1e-12 )
212+ {
213+ // No active triangles or flat region
214+ current_value = 1.0 ;
215+ }
216+ else
217+ {
218+ // To achieve max spacing d: dv = d * ||∇f||_min
219+ const double dv = max_spacing * min_grad;
220+ current_value += dv;
221+ }
222+
223+ if ( current_value < 1.0 )
224+ {
225+ levels.push_back ( std::min ( current_value, 1.0 ) );
226+ }
227+ }
228+
229+ if ( levels.back () < 1.0 - 1e-10 )
230+ {
231+ levels.push_back ( 1.0 );
232+ }
233+
234+ return levels;
235+ }
236+
160237int main ( int argc, char * argv[] )
161238{
162239 const std::vector<std::string> input_args (argv + 1 , argv + argc);
@@ -172,6 +249,10 @@ int main( int argc, char* argv[] )
172249 return SweepInputTestCases::ventricle ();
173250 else if ( std::find ( input_args.begin (), input_args.end (), " flange" ) != input_args.end () )
174251 return SweepInputTestCases::flange ();
252+ else if ( std::find ( input_args.begin (), input_args.end (), " flange_imprinted" ) != input_args.end () )
253+ return SweepInputTestCases::flange_imprinted ();
254+ else if ( std::find ( input_args.begin (), input_args.end (), " clevis" ) != input_args.end () )
255+ return SweepInputTestCases::clevis ();
175256 else if ( std::find ( input_args.begin (), input_args.end (), " cube" ) != input_args.end () )
176257 return SweepInputTestCases::twelveTetCube ();
177258 else if ( std::find ( input_args.begin (), input_args.end (), " bunny" ) != input_args.end () )
@@ -356,6 +437,9 @@ int main( int argc, char* argv[] )
356437 sweepEmbedding ( map, sweep_input.zero_bcs , sweep_input.one_bcs , normals );
357438 std::cout << " Laplace time 2: " << t.stop ( 4 ) << std::endl;
358439
440+ std::cout << " Level set values: " << computeEquallySpacedLevelSetValues ( map, ans, 0.7 ) << std::endl;
441+
442+
359443 const Eigen::Matrix3Xd grad = gradientsWithBoundaryCorrection ( map, sides, ans, normals );
360444
361445 if ( std::find ( input_args.begin (), input_args.end (), " output-laplace" ) != input_args.end () )
0 commit comments