I’m fiddling with a plugin and trying to determine a quick test for the existence/non-existence of a particular cell-data array, or point-data array and its overall range. I was hoping for a min/max vtkAlgorithm or equivalent but seem to be overseeing it. The problem is that my data are most likely to be multi-block with sub-block, the final leaves are either unstructured-grid or multi-piece containing unstructured-grid.
At the moment, I’ve coded up a GetRange() traversing method that works but is just so ugly that it cannot be the right way to do things. Attached is an example of my ad hoc min/max for a particular CellData or PointData field. Does anyone know of a simpler means of doing this?
// Works, but really cannot be correct (too ugly)
typedef std::pair<double,double> doublePair;
const doublePair invalidMinMax(GREAT, -GREAT);
template<class DataType>
doublePair getMinMax(DataType* input, const std::string& name)
{
return invalidMinMax;
}
const doublePair doMinMax(const doublePair& a, const doublePair& b)
{
return doublePair
(
std::min(a.first, b.first),
std::max(a.second, b.second)
);
}
doublePair getMinMax(vtkFieldData* input, const std::string& name)
{
// Info<< "minmax(" << name << ") of vtkFieldData" << nl;
doublePair result(invalidMinMax);
if (input && name.size())
{
// Get min/max
vtkDataArray* field = vtkDataArray::SafeDownCast
(
input->GetAbstractArray(name.c_str())
);
// May wish to handle vectors too?
if (field && field->GetNumberOfComponents() == 1)
{
double range[2]{ GREAT, -GREAT };
field->GetRange(range);
result.first = range[0];
result.second = range[1];
}
}
return result;
}
doublePair getMinMax(vtkCellData* input, const std::string& name)
{
// Info<< "minmax(" << name << ") of vtkCellArray" << nl;
return getMinMax(vtkFieldData::SafeDownCast(input), name);
}
doublePair getMinMax(vtkPointData* input, const std::string& name)
{
// Info<< "minmax(" << name << ") of vtkCellArray" << nl;
return getMinMax(vtkFieldData::SafeDownCast(input), name);
}
template<class FieldType>
doublePair getMinMax(vtkDataSet* input, const std::string& name)
{
// Info<< "minmax(" << name << ") FieldType" << nl;
return invalidMinMax;
}
template<>
doublePair getMinMax<vtkCellData>(vtkDataSet* input, const std::string& name)
{
// Info<< "minmax(" << name << ") vtkDataSet -> CellData" << nl;
if (input && name.size())
{
return getMinMax(input->GetCellData(), name);
}
return invalidMinMax;
}
template<>
doublePair getMinMax<vtkPointData>(vtkDataSet* input, const std::string& name)
{
// Info<< "minmax(" << name << ") vtkDataSet -> PointData" << nl;
if (input && name.size())
{
return getMinMax(input->GetPointData(), name);
}
return invalidMinMax;
}
template<class FieldType>
doublePair getMinMax(vtkMultiPieceDataSet* input, const std::string& name)
{
doublePair result(invalidMinMax);
const unsigned n =
((input && name.size()) ? input->GetNumberOfPieces() : 0);
// Info<< "minmax(" << name << ") vtkMultiPieceDataSet ("
// << n << ") pieces" << nl;
for (unsigned i = 0; i < n; ++i)
{
doublePair local = getMinMax<FieldType>
(
vtkDataSet::SafeDownCast(input->GetPiece(i)),
name
);
result = doMinMax(result, local);
}
return result;
}
emplate<class FieldType>
doublePair getMinMax(vtkMultiBlockDataSet* input, const std::string& name)
{
doublePair result(invalidMinMax);
const unsigned n =
((input && name.size()) ? input->GetNumberOfBlocks() : 0);
// Info<< "minmax(" << name << ") vtkMultiBlockDataSet ("
// << n << ") blocks" << nl;
for (unsigned i = 0; i < n; ++i)
{
vtkDataObject* obj = input->GetBlock(i);
vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::SafeDownCast(obj);
if (mb)
{
doublePair local = getMinMax<FieldType>(mb, name);
result = doMinMax(result, local);
continue;
}
vtkMultiPieceDataSet* mp = vtkMultiPieceDataSet::SafeDownCast(obj);
if (mp)
{
doublePair local = getMinMax<FieldType>(mp, name);
result = doMinMax(result, local);
continue;
}
vtkDataSet* dobj = vtkDataSet::SafeDownCast(obj);
if (dobj)
{
doublePair local = getMinMax<FieldType>(dobj, name);
result = doMinMax(result, local);
continue;
}
}
return result;
}
This whole thing would finally be called like this:
doublePair minmax = getMinMax<vtkCellData>(mesh, myFieldName);
// parallel reduce
We can also check if the lower/upper values are in the correct order. If they are not, then the field was not found at all.
There must surely be something simpler and more obvious, but I didn’t see it.
/mark