Hi Developers
I have used numerous times in the past, but something really weird is going on. I am beginning to think that it is the C++ that comes with VS2022.
I am basically just finding the min and max of a set of points. It is a part of a new Triangulate25D that at some point, I would like to make a contribution about. It operates on structured grids and sine the vtkThreshold only can output an unstructured grid, I incorporated some threasholding in the filter.
If I insert breakpoints just before the .Local()
statements, it ends up giving weird results. It is like multiple threads share some local variables. I have 20 cores - could that be the reason?
template <typename TPoints, typename TScalarArray>
struct vtkTriangulate25D::EvaluatePointsFunctor
{
using TLS = vtkSMPThreadLocal<std::array<double, 2>>;
TLS TLMinMaxDepth;
vtkTriangulate25D* Self;
vtkDataSet* Input;
TPoints* Points;
TScalarArray* ScalarsArray;
vtkIdType NumberOfPoints;
double RangeLow;
double RangeHigh;
vtkNew<vtkUnsignedCharArray> ValidityArray;
EvaluatePointsFunctor(
vtkTriangulate25D* self, vtkDataSet* input, TPoints* points, TScalarArray* scalarsArray)
: Self(self)
, Input(input)
, Points(points)
, ScalarsArray(scalarsArray)
, NumberOfPoints(input->GetNumberOfPoints())
, RangeLow(0.0)
, RangeHigh(0.0)
{
this->ValidityArray->SetNumberOfComponents(1);
this->ValidityArray->SetNumberOfValues(this->NumberOfPoints);
auto validityArray = vtk::DataArrayValueRange<1>(this->ValidityArray);
std::fill(std::begin(validityArray), std::end(validityArray), 0);
if (this->NumberOfPoints > 0)
{
// ensure that internal structures are initialized.
this->Input->GetPoint(0);
}
}
void Initialize()
{
std::array<double, 2>& minmax = this->TLMinMaxDepth.Local();
minmax[0] = VTK_DOUBLE_MAX;
minmax[1] = VTK_DOUBLE_MIN;
}
void operator()(vtkIdType begin, vtkIdType end)
{
const bool isFirst = false; // vtkSMPTools::GetSingleThread();
const auto& scalars = vtk::DataArrayTupleRange(this->ScalarsArray);
const auto& points = vtk::DataArrayTupleRange<3>(this->Points);
auto& validity = vtk::DataArrayValueRange<1>(this->ValidityArray);
vtkIdType checkAbortInterval = std::min((end - begin) / 10 + 1, (vtkIdType)1000);
// TODO: API type of input and max
double minDepth = VTK_DOUBLE_MAX;
double maxDepth = VTK_DOUBLE_MIN;
for (vtkIdType pointId = begin; pointId < end; ++pointId)
{
if (pointId % checkAbortInterval == 0)
{
if (isFirst)
{
this->Self->CheckAbort();
}
if (this->Self->GetAbortOutput())
{
break;
}
}
int keepPoint = 0;
keepPoint = this->Self->EvaluateComponents(scalars, pointId);
validity[pointId] = keepPoint ? MarkPointValid : 0;
if (keepPoint)
{
auto point = points[pointId];
double depth = point[Self->TwoDimType];
minDepth = std::min(minDepth, depth);
maxDepth = std::max(maxDepth, depth);
}
if (isFirst)
{
this->Self->UpdateProgress(end * 1.0 / this->NumberOfPoints * 1.0 / 3);
}
}
std::array<double, 2>& minmax = this->TLMinMaxDepth.Local();
minmax[0] = minDepth;
minmax[1] = maxDepth;
}
void Reduce()
{
using TLSIter = TLS::iterator;
TLSIter end = this->TLMinMaxDepth.end();
double minDepth = VTK_DOUBLE_MAX;
double maxDepth = VTK_DOUBLE_MIN;
for (TLSIter itr = this->TLMinMaxDepth.begin(); itr != end; ++itr)
{
std::array<double, 2>& minmax = *itr;
minDepth = std::min(minDepth, minmax[0]);
maxDepth = std::max(maxDepth, minmax[1]);
}
std::cout << "MinDepth: " << minDepth << std::endl;
std::cout << "MaxDepth: " << maxDepth << std::endl;
this->RangeLow = minDepth;
this->RangeHigh = maxDepth;
}
}