Add unit test for Box ImplicitFunction

This commit is contained in:
Patricia Kroll Fasel - 090207 2017-03-30 16:31:38 -06:00
parent 8190187d7d
commit 6ac2314796
2 changed files with 99 additions and 48 deletions

@ -194,63 +194,69 @@ public:
VTKM_EXEC_CONT VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3> &x) const FloatDefault Value(const vtkm::Vec<FloatDefault, 3> &x) const
{ {
vtkm::Vec<vtkm::IdComponent,3> inside(1, 1, 1); FloatDefault minDistance = vtkm::NegativeInfinity32();
vtkm::Vec<FloatDefault,3> dist(FloatDefault(0), FloatDefault(0), FloatDefault(0)); FloatDefault diff, t, dist;
FloatDefault insideDistance = vtkm::NegativeInfinity32(); FloatDefault distance = FloatDefault(0.0);
vtkm::IdComponent inside = 1;
for (vtkm::IdComponent d = 0; d < 3; d++) for (vtkm::IdComponent d = 0; d < 3; d++)
{ {
if (this->MinPoint[d] == this->MaxPoint[d]) diff = this->MaxPoint[d] - this->MinPoint[d];
if (diff != FloatDefault(0.0))
{ {
dist[d] = vtkm::Abs(x[d] - MinPoint[d]); t = (x[d] - this->MinPoint[d]) / diff;
if (dist[d] > 0.0) // Outside before the box
inside[d] = 0; if (t < FloatDefault(0.0))
}
else
{
// Calculate the distance of point to box boundary
if (x[d] < this->MinPoint[d])
{ {
// Point less than bounding box minimum (positive dist) inside = 0;
inside[d] = 0; dist = this->MinPoint[d] - x[d];
dist[d] = this->MinPoint[d] - x[d];
} }
else if (x[d] > this->MaxPoint[d]) // Outside after the box
else if (t > FloatDefault(1.0))
{ {
// Point greater than bounding box maximum (positive dist) inside = 0;
inside[d] = 0; dist = x[d] - this->MaxPoint[d];
dist[d] = x[d] - this->MaxPoint[d];
}
else if (x[d] <= ((this->MaxPoint[d] - this->MinPoint[d]) / FloatDefault(2)))
{
// Point inside box closer to minimum (negative dist)
dist[d] = this->MinPoint[d] - x[d];
if (dist[d] > insideDistance)
insideDistance = dist[d];
} }
else else
{ {
// Point inside box closer to maximum (negative dist) // Inside the box in lower half
dist[d] = x[d] - this->MaxPoint[d]; if (t <= FloatDefault(0.5))
if (dist[d] > insideDistance) {
insideDistance = dist[d]; dist = MinPoint[d] - x[d];
}
// Inside the box in upper half
else
{
dist = x[d] - MaxPoint[d];
}
if (dist > minDistance)
{
minDistance = dist;
}
} }
} }
else
{
dist = vtkm::Abs(x[d] - MinPoint[d]);
if (dist > FloatDefault(0.0))
{
inside = 0;
}
}
if (dist > FloatDefault(0.0))
{
distance += dist*dist;
}
} }
if (inside[0] && inside[1] && inside[2]) distance = vtkm::Sqrt(distance);
if (inside)
{ {
return(insideDistance); return minDistance;
} }
else else
{ {
FloatDefault distance = 0.f; return distance;
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (dist[d] > 0.0)
distance += dist[d] * dist[d];
}
return vtkm::Sqrt(distance);
} }
} }
@ -270,9 +276,9 @@ public:
vtkm::Vec<FloatDefault,3> normal; vtkm::Vec<FloatDefault,3> normal;
vtkm::Vec<FloatDefault,3> inside(FloatDefault(0), FloatDefault(0), FloatDefault(0)); vtkm::Vec<FloatDefault,3> inside(FloatDefault(0), FloatDefault(0), FloatDefault(0));
vtkm::Vec<FloatDefault,3> outside(FloatDefault(0), FloatDefault(0), FloatDefault(0)); vtkm::Vec<FloatDefault,3> outside(FloatDefault(0), FloatDefault(0), FloatDefault(0));
vtkm::Vec<FloatDefault,3> center((this->MaxPoint[0] - this->MinPoint[0]) / FloatDefault(2), vtkm::Vec<FloatDefault,3> center((this->MaxPoint[0] + this->MinPoint[0]) * FloatDefault(0.5),
(this->MaxPoint[1] - this->MinPoint[1]) / FloatDefault(2), (this->MaxPoint[1] + this->MinPoint[1]) * FloatDefault(0.5),
(this->MaxPoint[2] - this->MinPoint[2]) / FloatDefault(2)); (this->MaxPoint[2] + this->MinPoint[2]) * FloatDefault(0.5));
// Compute the location of the point with respect to the box // Compute the location of the point with respect to the box
// Point will lie in one of 27 separate regions around or within the box // Point will lie in one of 27 separate regions around or within the box
@ -293,19 +299,18 @@ public:
} }
else else
{ {
location[d] = 1;
if (x[d] <= center[d]) if (x[d] <= center[d])
{ {
// Inside the box low end // Inside the box low end
location[d] = 1;
inside[d] = -1.0;
dist = x[d] - this->MinPoint[d]; dist = x[d] - this->MinPoint[d];
inside[d] = -1.0;
} }
else else
{ {
// Inside the box high end // Inside the box high end
location[d] = 1;
inside[d] = 1.0;
dist = this->MaxPoint[d] - x[d]; dist = this->MaxPoint[d] - x[d];
inside[d] = 1.0;
} }
if (dist < minDist) // dist is negative if (dist < minDist) // dist is negative
{ {
@ -315,7 +320,7 @@ public:
} }
} }
int indx = location[0] + 3*location[1] + 9*location[2]; vtkm::Id indx = location[0] + 3*location[1] + 9*location[2];
switch (indx) switch (indx)
{ {
// verts - gradient points away from center point // verts - gradient points away from center point
@ -359,7 +364,7 @@ public:
normal[minAxis] = inside[minAxis]; normal[minAxis] = inside[minAxis];
break; break;
default: default:
assert("check: impossible case." && 0); // reaching this line is a bug. VTKM_ASSERT(false);
break; break;
} }
return normal; return normal;

@ -74,6 +74,48 @@ struct TestingImplicitFunctions
}; };
static void TestBoxValue()
{
typedef EvaluateImplicitFunction<vtkm::Box> EvalWorklet;
typedef vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapter>
EvalDispatcher;
FVec3 half(vtkm::Abs(GetRandomValue()), vtkm::Abs(GetRandomValue()), vtkm::Abs(GetRandomValue()));
FVec3 minPoint(GetRandomValue(), GetRandomValue(), GetRandomValue());
FVec3 maxPoint(minPoint[0] + 2.f * half[0], minPoint[1] + 2.f * half[1], minPoint[2] + 2.f * half[2]);
vtkm::Box box(minPoint, maxPoint);
FVec3 data[8] = { minPoint,
maxPoint,
minPoint + FVec3(FloatDefault(0), half[1], half[2]),
minPoint + FVec3(half[0], FloatDefault(0), half[2]),
minPoint + FVec3(half[0], half[1], FloatDefault(0)),
minPoint + half,
minPoint - half,
maxPoint + half
};
vtkm::cont::ArrayHandle<FVec3> points = vtkm::cont::make_ArrayHandle(data, 8);
EvalWorklet eval(box);
vtkm::cont::ArrayHandle<FloatDefault> values;
EvalDispatcher(eval).Invoke(points, values);
vtkm::cont::ArrayHandle<FloatDefault>::PortalConstControl portal =
values.GetPortalConstControl();
bool success = test_equal(portal.Get(0), FloatDefault(0.0) ) &&
test_equal(portal.Get(1), FloatDefault(0.0) ) &&
test_equal(portal.Get(2), FloatDefault(0.0) ) &&
test_equal(portal.Get(3), FloatDefault(0.0) ) &&
test_equal(portal.Get(4), FloatDefault(0.0) ) &&
(portal.Get(5) < 0.0) &&
(portal.Get(6) > 0.0) &&
(portal.Get(7) > 0.0);
VTKM_TEST_ASSERT(success, "Box: did not get expected results.");
}
static void TestSphereValue() static void TestSphereValue()
{ {
typedef EvaluateImplicitFunction<vtkm::Sphere> EvalWorklet; typedef EvaluateImplicitFunction<vtkm::Sphere> EvalWorklet;
@ -158,6 +200,10 @@ struct TestingImplicitFunctions
{ {
TestPlaneValue(); TestPlaneValue();
} }
for (int i = 0; i < 50; ++i)
{
TestBoxValue();
}
} }
}; };