// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-FileCopyrightText: Copyright (c) Kitware, Inc. // SPDX-FileCopyrightText: Copyright 2012 Sandia Corporation. // SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Sandia-USGov #ifndef vtkmlib_DataArrayConverters_h #define vtkmlib_DataArrayConverters_h #include "vtkAcceleratorsVTKmCoreModule.h" //required for correct implementation #include "vtkmConfigCore.h" //required for general viskores setup #include "vtkAOSDataArrayTemplate.h" #include "vtkAffineArray.h" #include "vtkConstantArray.h" #include "vtkSOADataArrayTemplate.h" #include "vtkLogger.h" #include #include #include #include #include #include #include #include #include #include #include #include // for std::underlying_type #include // for std::pair namespace viskores { namespace cont { class CoordinateSystem; } } VTK_ABI_NAMESPACE_BEGIN class vtkDataArray; class vtkPoints; VTK_ABI_NAMESPACE_END namespace tovtkm { VTK_ABI_NAMESPACE_BEGIN /// Temporary name for arrays converted from VTK that do not have a name. /// Unnamed arrays seem to be supported by VTK, but Viskores requires all fields to have a name. /// inline static const char* NoNameVTKFieldName() { static const char* name = "NoNameVTKField"; return name; } template viskores::cont::ArrayHandleBasic vtkAOSDataArrayToFlatArrayHandle( vtkAOSDataArrayTemplate* input) { // Register a reference to the input here to make sure the array cannot // be deleted before the `ArrayHandle` is done with it. (Note that you // will still get problems if the `vtkAOSDataArrayTemplate` gets resized. input->Register(nullptr); auto deleter = [](void* container) { vtkAOSDataArrayTemplate* vtkArray = reinterpret_cast*>(container); vtkArray->UnRegister(nullptr); }; auto reallocator = [](void*& memory, void*& container, viskores::BufferSizeType oldSize, viskores::BufferSizeType newSize) { vtkAOSDataArrayTemplate* vtkArray = reinterpret_cast*>(container); if ((vtkArray->GetPointer(0) != memory) || (vtkArray->GetNumberOfValues() != oldSize)) { vtkLog(ERROR, "Dangerous inconsistency found between pointers for VTK and Viskores. " "Was the VTK array resized outside of Viskores?"); } vtkArray->SetNumberOfValues(newSize); memory = vtkArray->GetPointer(0); }; return viskores::cont::ArrayHandleBasic( input->GetPointer(0), input, input->GetNumberOfValues(), deleter, reallocator); } template viskores::cont::ArrayHandleBasic vtkSOADataArrayToComponentArrayHandle( vtkSOADataArrayTemplate* input, int componentIndex) { // Register for each component (as each will have the deleter call to // unregister). input->Register(nullptr); using ContainerPair = std::pair*, int>; ContainerPair* componentInput = new ContainerPair(input, componentIndex); auto deleter = [](void* container) { ContainerPair* containerPair = reinterpret_cast(container); containerPair->first->UnRegister(nullptr); delete containerPair; }; auto reallocator = [](void*& memory, void*& container, viskores::BufferSizeType vtkNotUsed(oldSize), viskores::BufferSizeType newSize) { ContainerPair* containerPair = reinterpret_cast(container); containerPair->first->SetNumberOfTuples(newSize); memory = containerPair->first->GetComponentArrayPointer(containerPair->second); }; return viskores::cont::ArrayHandleBasic(input->GetComponentArrayPointer(componentIndex), componentInput, input->GetNumberOfTuples(), deleter, reallocator); } template viskores::cont::ArrayHandleRuntimeVec vtkDataArrayToArrayHandle( vtkAOSDataArrayTemplate* input) { auto flatArray = vtkAOSDataArrayToFlatArrayHandle(input); return viskores::cont::make_ArrayHandleRuntimeVec(input->GetNumberOfComponents(), flatArray); } template viskores::cont::ArrayHandleRecombineVec vtkDataArrayToArrayHandle( vtkSOADataArrayTemplate* input) { // Wrap each component array in a basic array handle, convert that to a // strided array, and then add that as a component to the returned // recombined vec. viskores::cont::ArrayHandleRecombineVec output; for (int componentIndex = 0; componentIndex < input->GetNumberOfComponents(); ++componentIndex) { auto componentArray = vtkSOADataArrayToComponentArrayHandle(input, componentIndex); output.AppendComponentArray( viskores::cont::ArrayExtractComponent(componentArray, 0, viskores::CopyFlag::Off)); } return output; } template viskores::cont::ArrayHandleConstant vtkDataArrayToArrayHandle( vtkConstantArray::ComponentType>* input) { return viskores::cont::ArrayHandleConstant( VecT{ input->GetBackend()->Value }, input->GetNumberOfTuples()); } template viskores::cont::UnknownArrayHandle vtkDataArrayToUnknownArrayHandle(vtkConstantArray* input) { switch (input->GetNumberOfComponents()) { case 1: return vtkDataArrayToArrayHandle(input); case 2: return vtkDataArrayToArrayHandle>(input); case 3: return vtkDataArrayToArrayHandle>(input); case 4: return vtkDataArrayToArrayHandle>(input); default: vtkGenericWarningMacro(<< "Cannot convert constant array with " << input->GetNumberOfComponents() << " components."); return viskores::cont::UnknownArrayHandle{}; } } template viskores::cont::UnknownArrayHandle vtkDataArrayToUnknownArrayHandle(vtkAffineArray* input) { if (input->GetNumberOfComponents() != 1) { vtkGenericWarningMacro(<< "Cannot convert affine array with " << input->GetNumberOfComponents() << " components."); return viskores::cont::UnknownArrayHandle{}; } T start = input->GetBackend()->Intercept; T step = input->GetBackend()->Slope; viskores::Id length = input->GetNumberOfValues(); if ((start == 0) && (step == 1)) { // Represent as an index array, which is less versatile but faster and has // better supported conversions. This could cause a type conversion, but all // values are exactly integers. return viskores::cont::ArrayHandleIndex(length); } else { return viskores::cont::ArrayHandleCounting(start, step, length); } } template viskores::cont::UnknownArrayHandle vtkDataArrayToUnknownArrayHandle(DataArrayType* input) { return vtkDataArrayToArrayHandle(input); } enum class FieldsFlag { None = 0x0, Points = 0x1, Cells = 0x2, PointsAndCells = Points | Cells }; VTK_ABI_NAMESPACE_END } namespace fromvtkm { VTK_ABI_NAMESPACE_BEGIN VTKACCELERATORSVTKMCORE_EXPORT vtkDataArray* Convert(const viskores::cont::Field& input); VTKACCELERATORSVTKMCORE_EXPORT vtkDataArray* Convert(const viskores::cont::UnknownArrayHandle& input, const std::string& name); VTKACCELERATORSVTKMCORE_EXPORT vtkPoints* Convert(const viskores::cont::CoordinateSystem& input); VTK_ABI_NAMESPACE_END } VTK_ABI_NAMESPACE_BEGIN inline tovtkm::FieldsFlag operator&(const tovtkm::FieldsFlag& a, const tovtkm::FieldsFlag& b) { using T = std::underlying_type::type; return static_cast(static_cast(a) & static_cast(b)); } inline tovtkm::FieldsFlag operator|(const tovtkm::FieldsFlag& a, const tovtkm::FieldsFlag& b) { using T = std::underlying_type::type; return static_cast(static_cast(a) | static_cast(b)); } VTK_ABI_NAMESPACE_END #endif // vtkmlib_ArrayConverters_h /* VTK-HeaderTest-Exclude: DataArrayConverters.h */