Refactor the structs to classes.

This commit is contained in:
Nick Thompson 2021-04-09 14:54:12 -04:00
parent eac6c21c84
commit 7b95ef5975

@ -19,34 +19,53 @@
// The logistic map is xᵢ₊₁ = rxᵢ(1-xᵢ).
// If we start this iteration out at (say) x₀ = 0.5, the map has "transients",
// which we must iterate away to produce the final image.
struct LogisticBurnIn : public vtkm::worklet::WorkletMapField
template <typename T>
class LogisticBurnIn : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(WholeArrayOut);
using ExecutionSignature = void(_1, WorkIndex);
template <typename OutputArrayPortalType>
VTKM_EXEC void operator()(OutputArrayPortalType& outputArrayPortal, vtkm::Id workIndex) const
public:
LogisticBurnIn(T rmin, vtkm::Id width)
: rmin_(rmin)
, width_(width)
{
vtkm::Id width = outputArrayPortal.GetNumberOfValues();
double rmin = 2.9;
double r = rmin + (4.0 - rmin) * workIndex / (width - 1);
double x = 0.5;
}
using ControlSignature = void(FieldOut);
using ExecutionSignature = _1(WorkIndex);
VTKM_EXEC T operator()(vtkm::Id workIndex) const
{
T r = rmin_ + (4.0 - rmin_) * workIndex / (width_ - 1);
T x = 0.5;
// 2048 should be enough iterations to get rid of the transients:
int n = 0;
while (n++ < 2048)
{
x = r * x * (1 - x);
}
outputArrayPortal.Set(workIndex, x);
return x;
}
private:
T rmin_;
vtkm::Id width_;
};
// After burn-in, the iteration is periodic but in general not convergent,
// i.e., for large enough i, there exists an integer p > 0 such that
// xᵢ₊ₚ = xᵢ for all i.
// So color the pixels corresponding to xᵢ, xᵢ₊₁, .. xᵢ₊ₚ.
struct LogisticLimitPoints : public vtkm::worklet::WorkletMapField
template <typename T>
class LogisticLimitPoints : public vtkm::worklet::WorkletMapField
{
public:
LogisticLimitPoints(T rmin, vtkm::Id width, vtkm::Id height)
: rmin_(rmin)
, width_(width)
, height_(height)
{
orange_ = vtkm::Vec4f(1.0, 0.5, 0.0, 0.0);
}
using ControlSignature = void(WholeArrayIn, WholeArrayOut);
using ExecutionSignature = void(_1, _2, WorkIndex);
@ -55,22 +74,23 @@ struct LogisticLimitPoints : public vtkm::worklet::WorkletMapField
OutputArrayPortalType& outputArrayPortal,
vtkm::Id workIndex) const
{
vtkm::Id width = inputArrayPortal.GetNumberOfValues();
double x = inputArrayPortal.Get(workIndex);
double rmin = 2.9;
double r = rmin + (4.0 - rmin) * workIndex / (width - 1);
vtkm::Vec4f orange(1.0, 0.5, 0.0, 0.0);
T x = inputArrayPortal.Get(workIndex);
T r = rmin_ + (4.0 - rmin_) * workIndex / (width_ - 1);
// We can't display need more limit points than pixels of height:
vtkm::Id limit_points = 0;
vtkm::Id height = 1800;
while (limit_points++ < height)
while (limit_points++ < height_)
{
vtkm::Id j = vtkm::Round(x * (height - 1));
outputArrayPortal.Set(j * width + workIndex, orange);
vtkm::Id j = vtkm::Round(x * (height_ - 1));
outputArrayPortal.Set(j * width_ + workIndex, orange_);
x = r * x * (1 - x);
}
}
private:
T rmin_;
vtkm::Id width_;
vtkm::Id height_;
vtkm::Vec4f orange_;
};
@ -84,7 +104,9 @@ int main()
vtkm::cont::ArrayHandle<double> x;
x.Allocate(width);
vtkm::cont::Invoker invoke;
invoke(LogisticBurnIn{}, x);
double rmin = 2.9;
auto burnIn = LogisticBurnIn<double>(rmin, width);
invoke(burnIn, x);
vtkm::cont::ArrayHandle<vtkm::Vec4f> pixels;
pixels.Allocate(width * height);
@ -93,8 +115,9 @@ int main()
{
wp.Set(i, vtkm::Vec4f(0, 0, 0, 0));
}
auto limitPoints = LogisticLimitPoints<double>(rmin, width, height);
invoke(LogisticLimitPoints{}, x, pixels);
invoke(limitPoints, x, pixels);
std::string colorFieldName = "pixels";
ds.AddPointField(colorFieldName, pixels);
std::string filename = "logistic.png";