@@ -57,32 +57,55 @@ using namespace SCIRun;
5757using namespace SCIRun ::Core;
5858using namespace SCIRun ::Core::Logging;
5959
60- AlgorithmInputName InterfaceWithCleaverAlgorithm::InputFields (" InputFields" );
61- AlgorithmOutputName InterfaceWithCleaverAlgorithm::OutputField (" OutputField" );
62- AlgorithmParameterName InterfaceWithCleaverAlgorithm::VerboseCheckBox (" VerboseCheckBox" );
63- AlgorithmParameterName InterfaceWithCleaverAlgorithm::PaddingCheckBox (" PaddingCheckBox" );
64- AlgorithmParameterName InterfaceWithCleaverAlgorithm::AbsoluteVolumeScalingRadioButton (" AbsoluteVolumeScalingRadioButton" );
65- AlgorithmParameterName InterfaceWithCleaverAlgorithm::RelativeVolumeScalingRadioButton (" RelativeVolumeScalingRadioButton" );
66- AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingSpinBox_X (" VolumeScalingSpinBox_X" );
67- AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingSpinBox_Y (" VolumeScalingSpinBox_Y" );
68- AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingSpinBox_Z (" VolumeScalingSpinBox_Z" );
60+ AlgorithmParameterName InterfaceWithCleaverAlgorithm::Verbose (" VerboseCheckBox" );
61+ AlgorithmParameterName InterfaceWithCleaverAlgorithm::Padding (" PaddingCheckBox" );
62+ AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingOption (" VolumeScalingOption" );
63+ AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingX (" VolumeScalingSpinBox_X" );
64+ AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingY (" VolumeScalingSpinBox_Y" );
65+ AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingZ (" VolumeScalingSpinBox_Z" );
6966
7067InterfaceWithCleaverAlgorithm::InterfaceWithCleaverAlgorithm ()
7168{
72- addParameter (VerboseCheckBox,true );
73- addParameter (PaddingCheckBox,true );
74- addParameter (AbsoluteVolumeScalingRadioButton,false );
75- addParameter (RelativeVolumeScalingRadioButton,true );
76- addParameter (VolumeScalingSpinBox_X,1.0 );
77- addParameter (VolumeScalingSpinBox_Y,1.0 );
78- addParameter (VolumeScalingSpinBox_Z,1.0 );
69+ addParameter (Verbose,true );
70+ addParameter (Padding,true );
71+ add_option (VolumeScalingOption, " Relative size" , " Absolute size|Relative size|None" );
72+ addParameter (VolumeScalingX,1.0 );
73+ addParameter (VolumeScalingY,1.0 );
74+ addParameter (VolumeScalingZ,1.0 );
7975}
8076
77+ boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol (FieldHandle field)
78+ {
79+ // TODO: this function assumes input is completely valid, may want to move various checks from run() function here.
80+
81+ VMesh* vmesh = field->vmesh ();
82+ VField* vfield = field->vfield ();
83+ VMesh::dimension_type dims;
84+ vmesh->get_dimensions ( dims );
85+ 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+
102+ return cleaverField;
103+ }
81104
82105FieldHandle InterfaceWithCleaverAlgorithm::run (const std::vector<FieldHandle>& input) const
83106{
84107 FieldHandle output;
85-
108+
86109 std::vector<FieldHandle> inputs;
87110 std::copy_if (input.begin (), input.end (), std::back_inserter (inputs), [](FieldHandle f) { return f; });
88111
@@ -93,144 +116,165 @@ FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& i
93116 }
94117 if (inputs.size ()<2 )
95118 {
96- THROW_ALGORITHM_INPUT_ERROR (" At least 2 indicator functions stored as float values are needed to run cleaver! " );
97- return FieldHandle ();
119+ THROW_ALGORITHM_INPUT_ERROR (" At least 2 indicator functions stored as float values are needed to run cleaver! " );
120+ return FieldHandle ();
98121 }
99-
122+
100123 std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;
101124 VMesh::dimension_type dims; int x=0 ,y=0 ,z=0 ;
102125 for (size_t p=1 ; p<inputs.size (); p++)
103126 {
104- VMesh* imesh1 = inputs[p]->vmesh ();
105-
127+ FieldHandle input = inputs[p];
128+ VMesh* imesh1 = input->vmesh ();
129+
106130 if ( !imesh1->is_structuredmesh () )
107131 {
108- THROW_ALGORITHM_INPUT_ERROR (" needs to be structured mesh!" );
109- } else
132+ THROW_ALGORITHM_INPUT_ERROR (" needs to be structured mesh!" );
133+ }
134+ else
110135 {
111- VField* vfield1 = inputs[p]->vfield ();
112- if (!vfield1->is_scalar ())
113- {
114- THROW_ALGORITHM_INPUT_ERROR (" values at the node needs to be scalar!" );
115- return FieldHandle ();
116- }
117-
118- imesh1->get_dimensions ( dims );
119- if (p==1 )
120- {
121- x=dims[0 ]; y=dims[1 ]; z=dims[2 ];
122- if (x<1 || y<1 || z<1 )
123- {
124- THROW_ALGORITHM_INPUT_ERROR (" Size of input fields should be non-zero !" );
125- }
126- } else
127- {
128- if ( dims[0 ]!=x || dims[1 ]!=y || dims[2 ]!=z)
129- {
130- THROW_ALGORITHM_INPUT_ERROR (" Size of input fields is inconsistent !" );
131- }
132- }
133-
134- if (dims.size ()!=3 )
135- {
136- THROW_ALGORITHM_INPUT_ERROR (" need a three dimensional indicator function" );
137- return FieldHandle ();
138- }
139-
140- if (vfield1->is_float ())
141- {
142- float * ptr = static_cast <float *>(vfield1->fdata_pointer ());
143- if (ptr)
136+ VField* vfield1 = input->vfield ();
137+ if (!vfield1->is_scalar ())
138+ {
139+ THROW_ALGORITHM_INPUT_ERROR (" values at the node needs to be scalar!" );
140+ return FieldHandle ();
141+ }
142+
143+ imesh1->get_dimensions ( dims );
144+ if (p==1 )
145+ {
146+ x=dims[0 ]; y=dims[1 ]; z=dims[2 ];
147+ if (x<1 || y<1 || z<1 )
148+ {
149+ THROW_ALGORITHM_INPUT_ERROR (" Size of input fields should be non-zero !" );
150+ }
151+ }
152+ else
144153 {
145- fields.push_back (boost::make_shared<Cleaver::FloatField>(dims[0 ], dims[1 ], dims[2 ], ptr));
146- } else
154+ if ( dims[0 ]!=x || dims[1 ]!=y || dims[2 ]!=z)
155+ {
156+ THROW_ALGORITHM_INPUT_ERROR (" Size of input fields is inconsistent !" );
157+ }
158+ }
159+
160+ if (dims.size ()!=3 )
147161 {
148- THROW_ALGORITHM_INPUT_ERROR (" float field is NULL pointer " );
162+ THROW_ALGORITHM_INPUT_ERROR (" need a three dimensional indicator function " );
149163 return FieldHandle ();
164+ }
165+
166+ if (vfield1->is_float ())
167+ {
168+ float * ptr = static_cast <float *>(vfield1->fdata_pointer ());
169+ if (ptr)
170+ {
171+ fields.push_back (makeCleaverFieldFromLatVol (input));
172+ }
173+ else
174+ {
175+ THROW_ALGORITHM_INPUT_ERROR (" float field is NULL pointer" );
176+ return FieldHandle ();
177+ }
150178 }
151- }
152179
153180 }
154-
181+
155182 }
156-
183+
157184 boost::shared_ptr<Cleaver::Volume> volume (new Cleaver::Volume (toVectorOfRawPointers (fields)));
158185
159- if ( get (VolumeScalingSpinBox_X).toDouble ()>0 && get (VolumeScalingSpinBox_Y).toDouble ()>0 && get (VolumeScalingSpinBox_Z).toDouble ()>0 )
186+ const double xScale = get (VolumeScalingX).toDouble ();
187+ const double yScale = get (VolumeScalingY).toDouble ();
188+ const double zScale = get (VolumeScalingZ).toDouble ();
189+
190+ if (xScale > 0 && yScale > 0 && zScale > 0 )
160191 {
161- if (get (AbsoluteVolumeScalingRadioButton).toBool ())
162- volume->setSize (get (VolumeScalingSpinBox_X).toDouble (),get (VolumeScalingSpinBox_Y).toDouble (),get (VolumeScalingSpinBox_Z).toDouble ());
163- else
164- if (get (RelativeVolumeScalingRadioButton).toBool ())
165- volume->setSize (get (VolumeScalingSpinBox_X).toDouble ()*volume->size ().x , get (VolumeScalingSpinBox_Y).toDouble ()*volume->size ().y , get (VolumeScalingSpinBox_Z).toDouble ()*volume->size ().z );
166- else
167- volume->setSize (dims[0 ],dims[1 ],dims[2 ]);
168- }
169- else
192+ const std::string scaling = get_option (VolumeScalingOption);
193+ if (" Absolute size" == scaling)
170194 {
171- volume->setSize (dims[0 ],dims[1 ],dims[2 ]);
172- THROW_ALGORITHM_INPUT_ERROR (" Invalid Scaling. Use Input sizes." );
195+ volume->setSize (xScale, yScale,zScale);
173196 }
174-
175- // / Padding is now optional!
176- boost::scoped_ptr<Cleaver::TetMesh> mesh (Cleaver::createMeshFromVolume (get (PaddingCheckBox).toBool () ? ((boost::shared_ptr<Cleaver::AbstractVolume>) new Cleaver::PaddedVolume (volume.get ())).get () : volume.get (), get (VerboseCheckBox).toBool ()));
177-
178- FieldInformation fi (" TetVolMesh" ,0 ," double" ); // /create output field
197+ else if (" Relative size" == scaling)
198+ {
199+ double newX = xScale*volume->size ().x ;
200+ double newY = yScale*volume->size ().y ;
201+ double newZ = zScale*volume->size ().z ;
202+ std::cout << " Cleaver setting volume size to " << newX << " ," << newY << " ," << newZ << std::endl;
203+ volume->setSize (newX, newY, newZ);
204+ }
205+ else // None
206+ volume->setSize (dims[0 ],dims[1 ],dims[2 ]);
207+ }
208+ else
209+ {
210+ THROW_ALGORITHM_INPUT_ERROR (" Invalid Scaling. Use Input sizes." );
211+ }
179212
180- output = CreateField (fi);
181- auto omesh = output->vmesh ();
182- auto ofield = output->vfield ();
213+ // / Padding is now optional!
214+ boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume (volume);
183215
184- auto nr_of_tets = mesh->tets .size ();
185- auto nr_of_verts = mesh->verts .size ();
216+ const bool verbose = get (Verbose).toBool ();
217+ const bool pad = get (Padding).toBool ();
218+ if (pad)
219+ paddedVolume.reset (new Cleaver::PaddedVolume (volume.get ()));
220+ boost::scoped_ptr<Cleaver::TetMesh> mesh (Cleaver::createMeshFromVolume (paddedVolume.get (), verbose));
186221
187- omesh->node_reserve (nr_of_verts);
188- omesh->elem_reserve (nr_of_tets);
222+ FieldInformation fi (" TetVolMesh" ,0 ," double" ); // /create output field
189223
190- for (auto i=0 ; i<nr_of_verts; i++)
191- {
192- omesh->add_point (Point (mesh->verts [i]->pos ().x ,mesh->verts [i]->pos ().y ,mesh->verts [i]->pos ().z ));
193- }
224+ output = CreateField (fi);
225+ auto omesh = output->vmesh ();
226+ auto ofield = output->vfield ();
194227
195- VMesh::Node::array_type vdata;
196- vdata.resize (4 );
197- std::vector<double > values (nr_of_tets);
198-
199- for (auto i=0 ; i<nr_of_tets; i++)
200- {
201- vdata[0 ]=mesh->tets [i]->verts [0 ]->tm_v_index ;
202- vdata[1 ]=mesh->tets [i]->verts [1 ]->tm_v_index ;
203- vdata[2 ]=mesh->tets [i]->verts [2 ]->tm_v_index ;
204- vdata[3 ]=mesh->tets [i]->verts [3 ]->tm_v_index ;
205- omesh->add_elem (vdata);
206- auto mat_label = mesh->tets [i]->mat_label +1 ;
207- values[i]=mat_label;
208- }
209- ofield->resize_values ();
210- ofield->set_values (values);
211- mesh->computeAngles ();
212- std::ostringstream ostr1;
213- ostr1 << " Number of tetrahedral elements:" << ofield->vmesh ()->num_elems () << std::endl;
214- ostr1 << " Number of tetrahedral nodes:" << ofield->vmesh ()->num_nodes () << std::endl;
215- ostr1 << " Number of tetrahedral nodes:" << ofield->vmesh ()->num_nodes () << std::endl;
216- ostr1 << " Worst Angle (min):" << mesh->min_angle << std::endl;
217- ostr1 << " Worst Angle (max):" << mesh->max_angle << std::endl;
218- ostr1 << " Volume:" << volume->size ().toString () << std::endl;
219-
220- remark (ostr1.str ());
228+ auto nr_of_tets = mesh->tets .size ();
229+ auto nr_of_verts = mesh->verts .size ();
230+
231+ omesh->node_reserve (nr_of_verts);
232+ omesh->elem_reserve (nr_of_tets);
233+
234+ for (auto i=0 ; i<nr_of_verts; i++)
235+ {
236+ omesh->add_point (Point (mesh->verts [i]->pos ().x ,mesh->verts [i]->pos ().y ,mesh->verts [i]->pos ().z ));
237+ }
238+
239+ VMesh::Node::array_type vdata;
240+ vdata.resize (4 );
241+ std::vector<double > values (nr_of_tets);
242+
243+ for (auto i=0 ; i<nr_of_tets; i++)
244+ {
245+ vdata[0 ]=mesh->tets [i]->verts [0 ]->tm_v_index ;
246+ vdata[1 ]=mesh->tets [i]->verts [1 ]->tm_v_index ;
247+ vdata[2 ]=mesh->tets [i]->verts [2 ]->tm_v_index ;
248+ vdata[3 ]=mesh->tets [i]->verts [3 ]->tm_v_index ;
249+ omesh->add_elem (vdata);
250+ auto mat_label = mesh->tets [i]->mat_label +1 ;
251+ values[i]=mat_label;
252+ }
253+ ofield->resize_values ();
254+ ofield->set_values (values);
255+ mesh->computeAngles ();
256+ 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;
260+ ostr1 << " Worst Angle (min):" << mesh->min_angle << std::endl;
261+ ostr1 << " Worst Angle (max):" << mesh->max_angle << std::endl;
262+ ostr1 << " Volume:" << volume->size ().toString () << std::endl;
263+
264+ remark (ostr1.str ());
221265
222266 return output;
223267}
224268
225269AlgorithmOutput InterfaceWithCleaverAlgorithm::run_generic (const AlgorithmInput& input) const
226270{
227- auto inputfields = input.getList <Field>(InputFields);
228-
229- FieldHandle output_fld;
230- output_fld= run (inputfields);
231- if ( !output_fld ) THROW_ALGORITHM_PROCESSING_ERROR (" False returned on legacy run call." );
271+ auto inputfields = input.getList <Field>(Variables:: InputFields);
272+
273+ FieldHandle output_fld = run (inputfields);
274+ if ( !output_fld )
275+ THROW_ALGORITHM_PROCESSING_ERROR (" Null returned on legacy run call." );
232276
233277 AlgorithmOutput output;
234- output[OutputField] = output_fld;
278+ output[Variables:: OutputField] = output_fld;
235279 return output;
236280}
0 commit comments