Skip to content

Commit b127614

Browse files
committed
Merge pull request #667 from moritzdannhauer/origin/CleaverFix
Origin/cleaver fix
2 parents 9fabc3b + 7309814 commit b127614

File tree

3 files changed

+728
-78
lines changed

3 files changed

+728
-78
lines changed

src/Core/Algorithms/Field/InterfaceWithCleaverAlgorithm.cc

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -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

5357
using namespace SCIRun::Core::Algorithms;
5458
using 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

105113
FieldHandle 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;

src/Core/Algorithms/Field/Tests/InterfaceWithCleaverAlgorithmTests.cc

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -42,46 +42,48 @@ using namespace SCIRun::Core::Algorithms::Fields;
4242
using namespace SCIRun::TestUtils;
4343

4444

45-
FieldHandle SphereSignedDistanceField(bool negative)
45+
FieldHandle BoxSignedDistanceField(bool negative)
4646
{
4747

4848
FieldInformation f("LatVolMesh", 1, "float");
49-
size_type size = 5;
50-
Point minb(-2.0, -2.0, -2.0);
51-
Point maxb(2.0, 2.0, 2.0);
49+
size_type size = 3;
50+
Point minb(-1.0, -1.0, -1.0);
51+
Point maxb(1.0, 1.0, 1.0);
5252
MeshHandle omesh = CreateMesh(f, size, size, size, minb, maxb);
5353
FieldHandle ofield = CreateField(f,omesh);
54-
std::vector<double> values(125);
55-
values[0]=0.9641;values[1]=0.5;values[2]=0.32843;values[3]=0.5;values[4]=0.9641;values[5]=0.5;
56-
values[6]=-0.05051;values[7]=-0.26393;values[8]=-0.05051;values[9]=0.5;values[10]=0.32843;
57-
values[11]=-0.26393;values[12]=-0.5;values[13]=-0.26393;values[14]=0.32843;values[15]=0.5;
58-
values[16]=-0.05051;values[17]=-0.26393;values[18]=-0.05051;values[19]=0.5;values[20]=0.9641;
59-
values[21]=0.5;values[22]=0.32843;values[23]=0.5;values[24]=0.9641;values[25]=0.5;
60-
values[26]=-0.05051;values[27]=-0.26393;values[28]=-0.05051;values[29]=0.5;
61-
values[30]=-0.05051;values[31]=-0.76795;values[32]=-1.0858;values[33]=-0.76795;
62-
values[34]=-0.05051;values[35]=-0.26393;values[36]=-1.0858;values[37]=-1.5;
63-
values[38]=-1.0858;values[39]=-0.26393;values[40]=-0.05051;values[41]=-0.76795;
64-
values[42]=-1.0858;values[43]=-0.76795;values[44]=-0.05051;values[45]=0.5;values[46]=-0.05051;
65-
values[47]=-0.26393;values[48]=-0.05051;values[49]=0.5;values[50]=0.32843;values[51]=-0.26393;
66-
values[52]=-0.5;values[53]=-0.26393;values[54]=0.32843;values[55]=-0.26393;values[56]=-1.0858;
67-
values[57]=-1.5;values[58]=-1.0858;values[59]=-0.26393;values[60]=-0.5;values[61]=-1.5;
68-
values[62]=-2.5;values[63]=-1.5;values[64]=-0.5;values[65]=-0.26393;values[66]=-1.0858;
69-
values[67]=-1.5;values[68]=-1.0858;values[69]=-0.26393;values[70]=0.32843;values[71]=-0.26393;
70-
values[72]=-0.5;values[73]=-0.26393;values[74]=0.32843;values[75]=0.5;values[76]=-0.05051;
71-
values[77]=-0.26393;values[78]=-0.05051;values[79]=0.5;values[80]=-0.05051;values[81]=-0.76795;
72-
values[82]=-1.0858;values[83]=-0.76795;values[84]=-0.05051;values[85]=-0.26393;values[86]=-1.0858;
73-
values[87]=-1.5;values[88]=-1.0858;values[89]=-0.26393;values[90]=-0.05051;values[91]=-0.76795;
74-
values[92]=-1.0858;values[93]=-0.76795;values[94]=-0.05051;values[95]=0.5;values[96]=-0.05051;
75-
values[97]=-0.26393;values[98]=-0.05051;values[99]=0.5;values[100]=0.9641;values[101]=0.5;
76-
values[102]=0.32843;values[103]=0.5;values[104]=0.9641;values[105]=0.5;values[106]=-0.05051;
77-
values[107]=-0.26393;values[108]=-0.05051;values[109]=0.5;values[110]=0.32843;values[111]=-0.26393;
78-
values[112]=-0.5;values[113]=-0.26393;values[114]=0.32843;values[115]=0.5;values[116]=-0.05051;
79-
values[117]=-0.26393;values[118]=-0.05051;values[119]=0.5;values[120]=0.9641;values[121]=0.5;
80-
values[122]=0.32843;values[123]=0.5;values[124]=0.9641;
54+
std::vector<double> values(27);
55+
56+
values[0]=-1.73205077648162841796875;
57+
values[1]=-1.41421353816986083984375;
58+
values[2]=-1.73205077648162841796875;
59+
values[3]=-1.41421353816986083984375;
60+
values[4]=-1;
61+
values[5]=-1.41421353816986083984375;
62+
values[6]=-1.73205077648162841796875;
63+
values[7]=-1.41421353816986083984375;
64+
values[8]=-1.73205077648162841796875;
65+
values[9]=-1.41421353816986083984375;
66+
values[10]=-1;
67+
values[11]=-1.41421353816986083984375;
68+
values[12]=-1;
69+
values[13]=0;
70+
values[14]=-1;
71+
values[15]=-1.41421353816986083984375;
72+
values[16]=-1;
73+
values[17]=-1.41421353816986083984375;
74+
values[18]=-1.73205077648162841796875;
75+
values[19]=-1.41421353816986083984375;
76+
values[20]=-1.73205077648162841796875;
77+
values[21]=-1.41421353816986083984375;
78+
values[22]=-1;
79+
values[23]=-1.41421353816986083984375;
80+
values[24]=-1.73205077648162841796875;
81+
values[25]=-1.41421353816986083984375;
82+
values[26]=-1.73205077648162841796875;
8183

8284
if (negative)
8385
{
84-
for (int i=0;i<125;i++)
86+
for (int i=0;i<27;i++)
8587
{
8688
values[i]=-values[i];
8789
}
@@ -95,16 +97,19 @@ using namespace SCIRun::TestUtils;
9597
TEST(CleaverInterfaceTest, SphereSignedDistanceFieldMatrix1)
9698
{
9799
InterfaceWithCleaverAlgorithm algo;
98-
FAIL() << "todo";
99100

100-
/* auto info = algo.run(SphereSignedDistanceField(false),SphereSignedDistanceField(true));
101+
std::vector<FieldHandle> inputs;
102+
inputs.push_back(BoxSignedDistanceField(true));
103+
inputs.push_back(BoxSignedDistanceField(false));
104+
105+
auto info = algo.run(inputs);
101106

102-
std::cout << "Number of mesh elements: " << info->vmesh()->num_elems() << std::endl;
103-
std::cout << "Number of mesh nodes: " << info->vmesh()->num_nodes() << std::endl;
104-
std::cout << "Number of mesh values: " << info->vfield()->num_values() << std::endl;
107+
std::cout << "Number of mesh elements: " << info->vmesh()->num_elems() << std::endl;
108+
std::cout << "Number of mesh nodes: " << info->vmesh()->num_nodes() << std::endl;
109+
std::cout << "Number of mesh values: " << info->vfield()->num_values() << std::endl;
105110

106-
ASSERT_TRUE(info->vmesh()->num_elems() != 98650);
107-
ASSERT_TRUE(info->vmesh()->num_nodes() != 18367);
108-
ASSERT_TRUE(info->vfield()->num_values() != 98650);
109-
*/
111+
ASSERT_TRUE(info->vmesh()->num_elems() == 4326);
112+
ASSERT_TRUE(info->vmesh()->num_nodes() == 908);
113+
ASSERT_TRUE(info->vfield()->num_values() == 4326);
114+
110115
}

0 commit comments

Comments
 (0)