@@ -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,24 +78,38 @@ 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{
7983 // TODO: this function assumes input is completely valid, may want to move various checks from run() function here.
80-
8184 VMesh* vmesh = field->vmesh ();
8285 VField* vfield = field->vfield ();
8386 VMesh::dimension_type dims;
8487 vmesh->get_dimensions ( dims );
88+
8589 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-
90+
91+ auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0 ], dims[1 ], dims[2 ], ptr);
92+
93+ cleaverField->setCenter (Cleaver::FloatField::CellCentered);
94+
95+ BBox bbox=vmesh->get_bounding_box ();
96+ Point bmin, bmax;
97+ if (bbox.valid ())
98+ {
99+ bmin = bbox.min ();
100+ bmax = bbox.max ();
101+ }
102+ Cleaver::BoundingBox bb = Cleaver::BoundingBox (Cleaver::vec3::zero, Cleaver::vec3 (dims[0 ],dims[1 ],dims[2 ]));
103+ cleaverField->setBounds (bb);
104+ const Transform &transform = vmesh->get_transform ();
105+
106+ 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 ));
107+ if (IsNan (x_spacing)) x_spacing=1 ;
108+ if (IsNan (y_spacing)) y_spacing=1 ;
109+ if (IsNan (z_spacing)) z_spacing=1 ;
110+
111+ cleaverField->setScale (Cleaver::vec3 (x_spacing,y_spacing,z_spacing));
112+
95113 // TODO: Cleaver FloatField needs more setup (constructor is not sufficient)
96114 // 1.
97115 // setBounds(BoundingBox). Convert vmesh->get_bounding_box() to Cleaver BoundingBox.
@@ -105,7 +123,6 @@ boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleav
105123FieldHandle InterfaceWithCleaverAlgorithm::run (const std::vector<FieldHandle>& input) const
106124{
107125 FieldHandle output;
108-
109126 std::vector<FieldHandle> inputs;
110127 std::copy_if (input.begin (), input.end (), std::back_inserter (inputs), [](FieldHandle f) { return f; });
111128
@@ -119,10 +136,11 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
119136 THROW_ALGORITHM_INPUT_ERROR (" At least 2 indicator functions stored as float values are needed to run cleaver! " );
120137 return FieldHandle ();
121138 }
122-
139+
123140 std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;
141+
124142 VMesh::dimension_type dims; int x=0 ,y=0 ,z=0 ;
125- for (size_t p=1 ; p<inputs.size (); p++)
143+ for (size_t p=0 ; p<inputs.size (); p++)
126144 {
127145 FieldHandle input = inputs[p];
128146 VMesh* imesh1 = input->vmesh ();
@@ -141,7 +159,7 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
141159 }
142160
143161 imesh1->get_dimensions ( dims );
144- if (p==1 )
162+ if (p==0 )
145163 {
146164 x=dims[0 ]; y=dims[1 ]; z=dims[2 ];
147165 if (x<1 || y<1 || z<1 )
@@ -163,26 +181,39 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
163181 return FieldHandle ();
164182 }
165183
184+ // 0 = constant, 1 = linear
185+ if (0 != vfield1->basis_order ())
186+ {
187+ THROW_ALGORITHM_INPUT_ERROR (" Input data need to be defined on elements. You can use the module MapFieldDataFromNodeToElem to do that." );
188+ }
189+
166190 if (vfield1->is_float ())
167- {
191+ {
168192 float * ptr = static_cast <float *>(vfield1->fdata_pointer ());
169- if (ptr)
170- {
193+ if (ptr)
194+ {
171195 fields.push_back (makeCleaverFieldFromLatVol (input));
172196 }
173197 else
174198 {
175199 THROW_ALGORITHM_INPUT_ERROR (" float field is NULL pointer" );
176200 return FieldHandle ();
177201 }
202+ } else
203+ {
204+ THROW_ALGORITHM_INPUT_ERROR (" Input field needs to be a structured mesh (LatVOL) with float values defnied on the elements. " );
178205 }
179206
180207 }
181208
182209 }
183210
184211 boost::shared_ptr<Cleaver::Volume> volume (new Cleaver::Volume (toVectorOfRawPointers (fields)));
185-
212+ /*
213+ Cleaver::BoundingBox m_bounds=fields[0]->bounds();
214+ std::cout << "bsize: " << m_bounds.size.x << " " << m_bounds.size.y << " " << m_bounds.size.z << std::endl;
215+ std::cout << "borin: " << m_bounds.origin.x << " " << m_bounds.origin.y << " " << m_bounds.origin.z << std::endl;
216+ */
186217 const double xScale = get (VolumeScalingX).toDouble ();
187218 const double yScale = get (VolumeScalingY).toDouble ();
188219 const double zScale = get (VolumeScalingZ).toDouble ();
@@ -199,28 +230,31 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
199230 double newX = xScale*volume->size ().x ;
200231 double newY = yScale*volume->size ().y ;
201232 double newZ = zScale*volume->size ().z ;
202- std::cout << " Cleaver setting volume size to " << newX << " ," << newY << " ," << newZ << std::endl;
203233 volume->setSize (newX, newY, newZ);
204234 }
205235 else // None
236+ {
206237 volume->setSize (dims[0 ],dims[1 ],dims[2 ]);
238+ }
207239 }
208240 else
209241 {
210242 THROW_ALGORITHM_INPUT_ERROR (" Invalid Scaling. Use Input sizes." );
211243 }
212-
244+
213245 // / Padding is now optional!
214246 boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume (volume);
215-
216247 const bool verbose = get (Verbose).toBool ();
217248 const bool pad = get (Padding).toBool ();
218249 if (pad)
219250 paddedVolume.reset (new Cleaver::PaddedVolume (volume.get ()));
251+
252+ std::cout << " Creating Mesh with Volume Size " << paddedVolume->size ().toString () << std::endl;
253+
220254 boost::scoped_ptr<Cleaver::TetMesh> mesh (Cleaver::createMeshFromVolume (paddedVolume.get (), verbose));
221255
222256 FieldInformation fi (" TetVolMesh" ,0 ," double" ); // /create output field
223-
257+
224258 output = CreateField (fi);
225259 auto omesh = output->vmesh ();
226260 auto ofield = output->vfield ();
@@ -247,16 +281,15 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
247281 vdata[2 ]=mesh->tets [i]->verts [2 ]->tm_v_index ;
248282 vdata[3 ]=mesh->tets [i]->verts [3 ]->tm_v_index ;
249283 omesh->add_elem (vdata);
250- auto mat_label = mesh->tets [i]->mat_label + 1 ;
284+ auto mat_label = mesh->tets [i]->mat_label ;
251285 values[i]=mat_label;
252286 }
253287 ofield->resize_values ();
254288 ofield->set_values (values);
255289 mesh->computeAngles ();
256290 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;
291+ ostr1 << " Number of tetrahedral elements:" << nr_of_tets << std::endl;
292+ ostr1 << " Number of tetrahedral nodes:" << nr_of_verts << std::endl;
260293 ostr1 << " Worst Angle (min):" << mesh->min_angle << std::endl;
261294 ostr1 << " Worst Angle (max):" << mesh->max_angle << std::endl;
262295 ostr1 << " Volume:" << volume->size ().toString () << std::endl;
0 commit comments