@@ -31,7 +31,10 @@ ToDo: Padding is always enabled because of exit() in cleaver lib
3131*/
3232
3333// /TODO: fix include path to remove Externals/ part
34+
3435#include < Externals/cleaver/lib/FloatField.h>
36+ #include < Externals/cleaver/lib/vec3.h>
37+ #include < Externals/cleaver/lib/BoundingBox.h>
3538#include < Externals/cleaver/lib/Cleaver.h>
3639#include < Externals/cleaver/lib/InverseField.h>
3740#include < Externals/cleaver/lib/PaddedVolume.h>
@@ -49,6 +52,7 @@ ToDo: Padding is always enabled because of exit() in cleaver lib
4952#include < Core/Utils/StringUtil.h>
5053#include < boost/scoped_ptr.hpp>
5154#include < Core/Logging/Log.h>
55+ #include < Core/Math/MiscMath.h>
5256
5357using namespace SCIRun ::Core::Algorithms;
5458using namespace SCIRun ::Core::Algorithms::Fields;
@@ -74,38 +78,41 @@ InterfaceWithCleaverAlgorithm::InterfaceWithCleaverAlgorithm()
7478 addParameter (VolumeScalingZ,1.0 );
7579}
7680
77- boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol (FieldHandle field)
81+ boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol (FieldHandle field )
7882{
79- // TODO: this function assumes input is completely valid, may want to move various checks from run() function here.
80-
8183 VMesh* vmesh = field->vmesh ();
8284 VField* vfield = field->vfield ();
8385 VMesh::dimension_type dims;
8486 vmesh->get_dimensions ( dims );
87+
8588 float * ptr = static_cast <float *>(vfield->fdata_pointer ());
86- auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0 ], dims[1 ], dims[2 ], ptr);
87-
88- // 0 = constant, 1 = linear
89- if (0 == vfield->basis_order ())
90- cleaverField->setCenter (Cleaver::FloatField::CellCentered);
91- else if (1 == vfield->basis_order ())
92- cleaverField->setCenter (Cleaver::FloatField::NodeCentered);
93- // else: TODO? handle other bases, probably by throwing exception.
94-
95- // TODO: Cleaver FloatField needs more setup (constructor is not sufficient)
96- // 1.
97- // setBounds(BoundingBox). Convert vmesh->get_bounding_box() to Cleaver BoundingBox.
98- // 2.
99- // setScale(vec3). Need to figure out which vmesh function to call, and convert to Cleaver::vec3.
100- // 3. unit test heavily.
101-
89+
90+ auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0 ], dims[1 ], dims[2 ], ptr);
91+
92+ BBox bbox=vmesh->get_bounding_box ();
93+ Point bmin, bmax;
94+ if (bbox.valid ())
95+ {
96+ bmin = bbox.min ();
97+ bmax = bbox.max ();
98+ }
99+ Cleaver::BoundingBox bb = Cleaver::BoundingBox (Cleaver::vec3::zero, Cleaver::vec3 (dims[0 ],dims[1 ],dims[2 ]));
100+ cleaverField->setBounds (bb);
101+ const Transform &transform = vmesh->get_transform ();
102+
103+ int x_spacing=fabs (transform.get_mat_val (0 ,0 )), y_spacing=fabs (transform.get_mat_val (1 ,1 )), z_spacing=fabs (transform.get_mat_val (2 ,2 ));
104+ if (IsNan (x_spacing)) x_spacing=1 ;
105+ if (IsNan (y_spacing)) y_spacing=1 ;
106+ if (IsNan (z_spacing)) z_spacing=1 ;
107+
108+ cleaverField->setScale (Cleaver::vec3 (x_spacing,y_spacing,z_spacing));
109+
102110 return cleaverField;
103111}
104112
105113FieldHandle InterfaceWithCleaverAlgorithm::run (const std::vector<FieldHandle>& input) const
106114{
107115 FieldHandle output;
108-
109116 std::vector<FieldHandle> inputs;
110117 std::copy_if (input.begin (), input.end (), std::back_inserter (inputs), [](FieldHandle f) { return f; });
111118
@@ -119,10 +126,11 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
119126 THROW_ALGORITHM_INPUT_ERROR (" At least 2 indicator functions stored as float values are needed to run cleaver! " );
120127 return FieldHandle ();
121128 }
122-
129+
123130 std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;
131+
124132 VMesh::dimension_type dims; int x=0 ,y=0 ,z=0 ;
125- for (size_t p=1 ; p<inputs.size (); p++)
133+ for (size_t p=0 ; p<inputs.size (); p++)
126134 {
127135 FieldHandle input = inputs[p];
128136 VMesh* imesh1 = input->vmesh ();
@@ -141,7 +149,7 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
141149 }
142150
143151 imesh1->get_dimensions ( dims );
144- if (p==1 )
152+ if (p==0 )
145153 {
146154 x=dims[0 ]; y=dims[1 ]; z=dims[2 ];
147155 if (x<1 || y<1 || z<1 )
@@ -163,18 +171,27 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
163171 return FieldHandle ();
164172 }
165173
174+ // 0 = constant, 1 = linear
175+ if (1 != vfield1->basis_order ())
176+ {
177+ THROW_ALGORITHM_INPUT_ERROR (" Input data need to be defined on input mesh nodes." );
178+ }
179+
166180 if (vfield1->is_float ())
167- {
181+ {
168182 float * ptr = static_cast <float *>(vfield1->fdata_pointer ());
169- if (ptr)
170- {
183+ if (ptr)
184+ {
171185 fields.push_back (makeCleaverFieldFromLatVol (input));
172186 }
173187 else
174188 {
175189 THROW_ALGORITHM_INPUT_ERROR (" float field is NULL pointer" );
176190 return FieldHandle ();
177191 }
192+ } else
193+ {
194+ THROW_ALGORITHM_INPUT_ERROR (" Input field needs to be a structured mesh (best would be a LatVol) with float values defnied on the elements. " );
178195 }
179196
180197 }
@@ -199,35 +216,43 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
199216 double newX = xScale*volume->size ().x ;
200217 double newY = yScale*volume->size ().y ;
201218 double newZ = zScale*volume->size ().z ;
202- std::cout << " Cleaver setting volume size to " << newX << " ," << newY << " ," << newZ << std::endl;
203219 volume->setSize (newX, newY, newZ);
204220 }
205221 else // None
222+ {
206223 volume->setSize (dims[0 ],dims[1 ],dims[2 ]);
224+ }
207225 }
208226 else
209227 {
210228 THROW_ALGORITHM_INPUT_ERROR (" Invalid Scaling. Use Input sizes." );
211229 }
212-
230+
213231 // / Padding is now optional!
214232 boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume (volume);
215-
216233 const bool verbose = get (Verbose).toBool ();
217234 const bool pad = get (Padding).toBool ();
218235 if (pad)
219236 paddedVolume.reset (new Cleaver::PaddedVolume (volume.get ()));
237+
238+ std::cout << " Creating Mesh with Volume Size " << paddedVolume->size ().toString () << std::endl;
239+
220240 boost::scoped_ptr<Cleaver::TetMesh> mesh (Cleaver::createMeshFromVolume (paddedVolume.get (), verbose));
221241
222- FieldInformation fi (" TetVolMesh" ,0 ," double" ); // /create output field
242+ auto nr_of_tets = mesh->tets .size ();
243+ auto nr_of_verts = mesh->verts .size ();
244+
245+ if (nr_of_tets==0 || nr_of_verts==0 )
246+ {
247+ THROW_ALGORITHM_INPUT_ERROR (" Number of resulting tetrahedral nodes or elements is 0. If you disabled padding enable it and execute again. " );
248+ }
223249
250+ FieldInformation fi (" TetVolMesh" ,0 ," double" ); // /create output field
251+
224252 output = CreateField (fi);
225253 auto omesh = output->vmesh ();
226254 auto ofield = output->vfield ();
227255
228- auto nr_of_tets = mesh->tets .size ();
229- auto nr_of_verts = mesh->verts .size ();
230-
231256 omesh->node_reserve (nr_of_verts);
232257 omesh->elem_reserve (nr_of_tets);
233258
@@ -247,16 +272,15 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
247272 vdata[2 ]=mesh->tets [i]->verts [2 ]->tm_v_index ;
248273 vdata[3 ]=mesh->tets [i]->verts [3 ]->tm_v_index ;
249274 omesh->add_elem (vdata);
250- auto mat_label = mesh->tets [i]->mat_label + 1 ;
275+ auto mat_label = mesh->tets [i]->mat_label ;
251276 values[i]=mat_label;
252277 }
253278 ofield->resize_values ();
254279 ofield->set_values (values);
255280 mesh->computeAngles ();
256281 std::ostringstream ostr1;
257- ostr1 << " Number of tetrahedral elements:" << ofield->vmesh ()->num_elems () << std::endl;
258- ostr1 << " Number of tetrahedral nodes:" << ofield->vmesh ()->num_nodes () << std::endl;
259- ostr1 << " Number of tetrahedral nodes:" << ofield->vmesh ()->num_nodes () << std::endl;
282+ ostr1 << " Number of tetrahedral elements:" << nr_of_tets << std::endl;
283+ ostr1 << " Number of tetrahedral nodes:" << nr_of_verts << std::endl;
260284 ostr1 << " Worst Angle (min):" << mesh->min_angle << std::endl;
261285 ostr1 << " Worst Angle (max):" << mesh->max_angle << std::endl;
262286 ostr1 << " Volume:" << volume->size ().toString () << std::endl;
0 commit comments