Skip to content

Commit

Permalink
Experimenting with different code algorithms. NONE ARE WORKING. THIS …
Browse files Browse the repository at this point in the history
…COMMIT IS JUNK

The issue is that the outer virtual boundary Face Labels and the underlying FeatureIds
do not agree. I think we may need to store the actual index offset into the
FeatureIds array and then also store a reference to the FeatureIds array so that
we can get the data consistently.

Signed-off-by: Michael Jackson <[email protected]>
  • Loading branch information
imikejackson committed Dec 12, 2024
1 parent 156ad24 commit 5ef294a
Show file tree
Hide file tree
Showing 14 changed files with 305 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,21 @@ Result<> SurfaceNets::operator()()
auto voxelSize = imageGeom.getSpacing();
auto origin = imageGeom.getOrigin();

// X Y Z Ordering
IntVec3 arraySize(static_cast<int32>(gridDimensions[0]), static_cast<int32>(gridDimensions[1]), static_cast<int32>(gridDimensions[2]));

auto& featureIds = m_DataStructure.getDataAs<Int32Array>(m_InputValues->FeatureIdsArrayPath)->getDataStoreRef();

using LabelType = int32;
// THIS IS MAKING A COPY OF THE IMAGE GEOMETRY CELL "FEATURE IDS" array
using LabelType = int32_t;
std::vector<LabelType> labels(featureIds.getNumberOfTuples());
for(size_t idx = 0; idx < featureIds.getNumberOfTuples(); idx++)
{
labels[idx] = static_cast<LabelType>(featureIds[idx]);
}

MMSurfaceNet surfaceNet(labels.data(), arraySize.data(), voxelSize.data());
labels.resize(0); // Free that copy... because there is another copy in the surfaceNet object.

// Use current parameters to relax the SurfaceNet
if(m_InputValues->ApplySmoothing)
Expand Down Expand Up @@ -155,12 +158,15 @@ Result<> SurfaceNets::operator()()
nodeTypes[static_cast<usize>(vertIndex)] = static_cast<int8>(currentCellPtr->flag.numJunctions());
}
usize triangleCount = 0;
std::array<ptrdiff_t, 2> cellDataIndex = {0, 0};
// First Pass through to just count the number of triangles:
for(int idxVtx = 0; idxVtx < nodeCount; idxVtx++)
{
std::array<int32, 4> vertexIndices = {0, 0, 0, 0};
std::array<LabelType, 2> quadLabels = {0, 0};
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexIndices.data(), quadLabels.data()))
std::array<int32_t, 3> cellIndices = {0, 0, 0};

if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexIndices.data(), quadLabels.data(), cellIndices))
{
if(quadLabels[0] == MMSurfaceNet::Padding || quadLabels[1] == MMSurfaceNet::Padding)
{
Expand All @@ -178,7 +184,7 @@ Result<> SurfaceNets::operator()()
}
triangleCount += 2;
}
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexIndices.data(), quadLabels.data()))
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexIndices.data(), quadLabels.data(), cellIndices))
{
if(quadLabels[0] == MMSurfaceNet::Padding || quadLabels[1] == MMSurfaceNet::Padding)
{
Expand All @@ -196,7 +202,7 @@ Result<> SurfaceNets::operator()()
}
triangleCount += 2;
}
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexIndices.data(), quadLabels.data()))
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexIndices.data(), quadLabels.data(), cellIndices))
{
if(quadLabels[0] == MMSurfaceNet::Padding || quadLabels[1] == MMSurfaceNet::Padding)
{
Expand All @@ -221,6 +227,7 @@ Result<> SurfaceNets::operator()()
// Resize the face labels Int32Array
auto& faceLabels = m_DataStructure.getDataAs<Int32Array>(m_InputValues->FaceLabelsDataPath)->getDataStoreRef();
faceLabels.resizeTuples({triangleCount});
faceLabels.fill(-1000);

// Create a vector of TupleTransferFunctions for each of the Triangle Face to VertexType Data Arrays
std::vector<std::shared_ptr<AbstractTupleTransfer>> tupleTransferFunctions;
Expand All @@ -240,12 +247,29 @@ Result<> SurfaceNets::operator()()
std::array<int32, 4> vertexIndices = {0, 0, 0, 0};
std::array<LabelType, 2> quadLabels = {0, 0};
std::array<VertexData, 4> vData{};
std::array<int32_t, 3> cellIndices = {0, 0, 0};

constexpr size_t x_idx = 0;
constexpr size_t y_idx = 1;
constexpr size_t z_idx = 2;

for(int idxVtx = 0; idxVtx < nodeCount; idxVtx++)
{

// Back-bottom edge
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexIndices.data(), quadLabels.data()))
// std::array<int32_t, 3> cellIndex;
// cellMapPtr->getVertexCellIndex(idxVtx, cellIndex.data());
// std::cout << cellIndex[0] << ", " << cellIndex[1] << ", " << cellIndex[2] << std::endl;

GenerateTriangles(idxVtx, MMCellFlag::Edge::BackBottomEdge, cellMapPtr, imageGeom, triangleGeom, faceIndex, faceLabels, featureIds, tupleTransferFunctions);
GenerateTriangles(idxVtx, MMCellFlag::Edge::LeftBottomEdge, cellMapPtr, imageGeom, triangleGeom, faceIndex, faceLabels, featureIds, tupleTransferFunctions);
GenerateTriangles(idxVtx, MMCellFlag::Edge::LeftBackEdge, cellMapPtr, imageGeom, triangleGeom, faceIndex, faceLabels, featureIds, tupleTransferFunctions);

#if 0
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexIndices.data(), quadLabels.data(), cellIndices))
{
size_t cellIndex1 = cellIndices[z_idx] * gridDimensions[y_idx] * gridDimensions[x_idx] + cellIndices[y_idx] * gridDimensions[x_idx] + cellIndices[x_idx];
size_t cellIndex2 = (cellIndices[z_idx] - 1) * gridDimensions[y_idx] * gridDimensions[x_idx] + cellIndices[y_idx] * gridDimensions[x_idx] + cellIndices[x_idx];

vData[0] = {vertexIndices[0], 00.0f, 0.0f, 0.0f};
vData[1] = {vertexIndices[1], 00.0f, 0.0f, 0.0f};
vData[2] = {vertexIndices[2], 00.0f, 0.0f, 0.0f};
Expand All @@ -271,7 +295,7 @@ Result<> SurfaceNets::operator()()
// Copy any Cell Data to the Triangle Mesh
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, quadLabels[0], quadLabels[1], faceLabels);
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellIndex1, cellIndex2);
}

faceIndex++;
Expand All @@ -290,14 +314,17 @@ Result<> SurfaceNets::operator()()
// Copy any Cell Data to the Triangle Mesh
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, quadLabels[0], quadLabels[1], faceLabels);
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellIndex1, cellIndex2);
}
faceIndex++;
}

// Left-bottom edge
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexIndices.data(), quadLabels.data()))
// Left-bottom edge Y
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexIndices.data(), quadLabels.data(), cellIndices))
{
size_t cellIndex1 = cellIndices[z_idx] * gridDimensions[y_idx] * gridDimensions[x_idx] + cellIndices[y_idx] * gridDimensions[x_idx] + cellIndices[x_idx];
size_t cellIndex2 = cellIndices[z_idx] * (gridDimensions[y_idx] - 1) * gridDimensions[x_idx] + (cellIndices[y_idx] - 1) * gridDimensions[x_idx] + cellIndices[x_idx];

vData[0] = {vertexIndices[0], 00.0f, 0.0f, 0.0f};
vData[1] = {vertexIndices[1], 00.0f, 0.0f, 0.0f};
vData[2] = {vertexIndices[2], 00.0f, 0.0f, 0.0f};
Expand All @@ -323,7 +350,7 @@ Result<> SurfaceNets::operator()()
// Copy any Cell Data to the Triangle Mesh
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, quadLabels[0], quadLabels[1], faceLabels);
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellIndex1, cellIndex2);
}
faceIndex++;

Expand All @@ -341,14 +368,17 @@ Result<> SurfaceNets::operator()()
// Copy any Cell Data to the Triangle Mesh
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, quadLabels[0], quadLabels[1], faceLabels);
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellIndex1, cellIndex2);
}
faceIndex++;
}

// Left-back edge
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexIndices.data(), quadLabels.data()))
// Left-back edge X
if(cellMapPtr->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexIndices.data(), quadLabels.data(), cellIndices))
{
size_t cellIndex1 = cellIndices[z_idx] * gridDimensions[y_idx] * gridDimensions[x_idx] + cellIndices[y_idx] * gridDimensions[x_idx] + cellIndices[x_idx];
size_t cellIndex2 = cellIndices[z_idx] * gridDimensions[y_idx] * gridDimensions[x_idx] + cellIndices[y_idx] * gridDimensions[x_idx] + (cellIndices[x_idx] - 1);

vData[0] = {vertexIndices[0], 00.0f, 0.0f, 0.0f};
vData[1] = {vertexIndices[1], 00.0f, 0.0f, 0.0f};
vData[2] = {vertexIndices[2], 00.0f, 0.0f, 0.0f};
Expand All @@ -374,7 +404,7 @@ Result<> SurfaceNets::operator()()
// Copy any Cell Data to the Triangle Mesh
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, quadLabels[0], quadLabels[1], faceLabels);
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellIndex1, cellIndex2);
}
faceIndex++;

Expand All @@ -392,11 +422,134 @@ Result<> SurfaceNets::operator()()
// Copy any Cell Data to the Triangle Mesh
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, quadLabels[0], quadLabels[1], faceLabels);
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellIndex1, cellIndex2);
}
faceIndex++;
}
#endif
}

return {};
}

using LabelType = int32;

/**
*
* @param idxVtx
* @param edgeType
* @param cellMapPtr
* @param imageGeom
* @param triangleGeom
* @param faceIndex
* @param faceLabels
* @param tupleTransferFunctions
*/
void SurfaceNets::GenerateTriangles(int idxVtx, MMCellFlag::Edge edgeType, MMCellMap* cellMapPtr, const ImageGeom& imageGeom, TriangleGeom& triangleGeom, usize& faceIndex,
AbstractDataStore<int32_t>& faceLabels, AbstractDataStore<int32_t>& featureIds, std::vector<std::shared_ptr<AbstractTupleTransfer>>& tupleTransferFunctions)
{
auto gridDimensions = imageGeom.getDimensions();

std::array<int32, 4> vertexIndices = {0, 0, 0, 0};
std::array<LabelType, 2> quadLabels = {0, 0};
std::array<int32_t, 3> cellIndex = {0, 0, 0};
if(!cellMapPtr->getEdgeQuad(idxVtx, edgeType, vertexIndices.data(), quadLabels.data(), cellIndex))
{
return;
}
constexpr size_t x_idx = 0;
constexpr size_t y_idx = 1;
constexpr size_t z_idx = 2;

// cellIndex[x_idx] = (cellIndex[x_idx] > 0 ? cellIndex[x_idx] - 1 : cellIndex[x_idx]);
// cellIndex[y_idx] = (cellIndex[y_idx] > 0 ? cellIndex[y_idx] - 1 : cellIndex[y_idx]);
// cellIndex[z_idx] = (cellIndex[z_idx] > 0 ? cellIndex[z_idx] - 1 : cellIndex[z_idx]);

std::array<size_t, 2> cellOffset = {(cellIndex[z_idx] * gridDimensions[y_idx] * gridDimensions[x_idx]) + (cellIndex[y_idx] * gridDimensions[x_idx]) + cellIndex[x_idx], 0};

if(edgeType == MMCellFlag::Edge::LeftBottomEdge)
{
cellOffset[1] = cellOffset[0] + gridDimensions[x_idx];
}
else if(edgeType == MMCellFlag::Edge::BackBottomEdge)
{
cellOffset[1] = cellOffset[0] + 1;
}
else if(edgeType == MMCellFlag::Edge::LeftBackEdge)
{
cellOffset[1] = cellOffset[0] + gridDimensions[x_idx] * gridDimensions[y_idx];
}
else
{
throw std::runtime_error("SurfaceNets: GenerateTriangles used unknown enumeration for edge type");
}

std::array<VertexData, 4> vData = {VertexData{vertexIndices[0], 00.0f, 0.0f, 0.0f}, VertexData{vertexIndices[1], 00.0f, 0.0f, 0.0f}, VertexData{vertexIndices[2], 00.0f, 0.0f, 0.0f},
VertexData{vertexIndices[3], 00.0f, 0.0f, 0.0f}};

const bool isQuadFrontFacing = (quadLabels[0] < quadLabels[1]);

std::array<int, 6> triangleVtxIDs = {0, 0, 0, 0, 0, 0};
getQuadTriangleIDs(vData, isQuadFrontFacing, triangleVtxIDs);
std::array<usize, 3> t1 = {static_cast<usize>(triangleVtxIDs[0]), static_cast<usize>(triangleVtxIDs[1]), static_cast<usize>(triangleVtxIDs[2])};
triangleGeom.setFacePointIds(faceIndex, t1);
std::array<usize, 3> t2 = {static_cast<usize>(triangleVtxIDs[3]), static_cast<usize>(triangleVtxIDs[4]), static_cast<usize>(triangleVtxIDs[5])};
triangleGeom.setFacePointIds(faceIndex + 1, t2);

if(quadLabels[0] != -1 && quadLabels[1] != -1)
{
size_t firstIdx = 0;
size_t secIdx = 1;
if(quadLabels[1] < quadLabels[0])
{
firstIdx = 1;
secIdx = 0;
}

std::cout << quadLabels[firstIdx] << "\t" << quadLabels[secIdx] << "\t" << featureIds[cellOffset[firstIdx]] << '\t' << featureIds[cellOffset[secIdx]] << "\n";

faceLabels[faceIndex * 2] = (quadLabels[firstIdx] == -1 ? -1 : faceLabels[cellOffset[firstIdx]]); // quadLabels[firstIdx];
faceLabels[faceIndex * 2 + 1] = (quadLabels[secIdx] == -1 ? -1 : faceLabels[cellOffset[secIdx]]); // quadLabels[firstIdx];

faceLabels[(faceIndex + 1) * 2] = (quadLabels[firstIdx] == -1 ? -1 : faceLabels[cellOffset[firstIdx]]); // quadLabels[firstIdx];
faceLabels[(faceIndex + 1) * 2 + 1] = (quadLabels[secIdx] == -1 ? -1 : faceLabels[cellOffset[secIdx]]); // quadLabels[firstIdx];
}
else // One of the Quad Labels is -1, which means we are on the virtual border
{
// Assume the first Quad Label = -1
size_t firstIdx = 0;
size_t secIdx = 1;
if(quadLabels[1] == -1)
{
firstIdx = 1;
secIdx = 0;
}

std::cout << quadLabels[firstIdx] << "\t" << quadLabels[secIdx] << "\t" << featureIds[cellOffset[firstIdx]] << '\t' << featureIds[cellOffset[secIdx]] << "\n";

if(quadLabels[secIdx] != -1 && quadLabels[secIdx] != featureIds[cellOffset[secIdx]])
{
std::cout << " " << cellIndex[0] << "\t" << cellIndex[1] << "\t" << cellIndex[2] << "\n";
}

faceLabels[faceIndex * 2] = (quadLabels[firstIdx] == -1 ? -666 : faceLabels[cellOffset[firstIdx]]); // quadLabels[firstIdx];
faceLabels[faceIndex * 2 + 1] = (quadLabels[secIdx] == -1 ? -1 : faceLabels[cellOffset[secIdx]]); // quadLabels[firstIdx];

faceLabels[(faceIndex + 1) * 2] = (quadLabels[firstIdx] == -1 ? -666 : faceLabels[cellOffset[firstIdx]]); // quadLabels[firstIdx];
faceLabels[(faceIndex + 1) * 2 + 1] = (quadLabels[secIdx] == -1 ? -1 : faceLabels[cellOffset[secIdx]]); // quadLabels[firstIdx];

// Copy any Cell Data to the Triangle Mesh for the first triangle
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex, cellOffset[firstIdx], cellOffset[secIdx], faceLabels);
}
// Copy any Cell Data to the Triangle Mesh for the second triangle
for(size_t dataVectorIndex = 0; dataVectorIndex < m_InputValues->SelectedDataArrayPaths.size(); dataVectorIndex++)
{
tupleTransferFunctions[dataVectorIndex]->transfer(faceIndex + 1, cellOffset[firstIdx], cellOffset[secIdx], faceLabels);
}
}

// Increment the 'faceIndex' index by 2
faceIndex = faceIndex + 2;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
#pragma once

#include "SimplnxCore/Filters/Algorithms/TupleTransfer.hpp"
#include "SimplnxCore/SimplnxCore_export.hpp"
#include "SimplnxCore/SurfaceNets/MMCellFlag.h"

#include "simplnx/DataStructure/DataPath.hpp"
#include "simplnx/DataStructure/DataStructure.hpp"
#include "simplnx/DataStructure/Geometry/ImageGeom.hpp"
#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp"
#include "simplnx/Filter/IFilter.hpp"
#include "simplnx/Parameters/ArrayCreationParameter.hpp"
#include "simplnx/Parameters/ArraySelectionParameter.hpp"
#include "simplnx/Parameters/BoolParameter.hpp"
#include "simplnx/Parameters/DataGroupCreationParameter.hpp"
#include "simplnx/Parameters/MultiArraySelectionParameter.hpp"

class MMCellMap;

namespace nx::core
{

Expand Down Expand Up @@ -55,6 +61,9 @@ class SIMPLNXCORE_EXPORT SurfaceNets
const SurfaceNetsInputValues* m_InputValues = nullptr;
const std::atomic_bool& m_ShouldCancel;
const IFilter::MessageHandler& m_MessageHandler;

void GenerateTriangles(int idxVtx, MMCellFlag::Edge edgeType, MMCellMap* cellMapPtr, const ImageGeom& imageGeom, TriangleGeom& triangleGeom, usize& faceIndex, AbstractDataStore<int32_t>& featureIds,
AbstractDataStore<int32_t>& faceLabels, std::vector<std::shared_ptr<AbstractTupleTransfer>>& tupleTransferFunctions);
};

} // namespace nx::core
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class SIMPLNXCORE_EXPORT AbstractTupleTransfer
* @param secondcIndex
* @param forceSecondToZero
*/
virtual void transfer(size_t faceIndex, size_t firstcIndex, size_t secondcIndex, bool forceSecondToZero = false) = 0;
// virtual void transfer(size_t faceIndex, size_t firstcIndex, size_t secondcIndex, bool forceSecondToZero) = 0;

virtual void transfer(size_t faceIndex, size_t firstcIndex) = 0;

Expand Down Expand Up @@ -82,21 +82,21 @@ class TransferTuple : public AbstractTupleTransfer
* @param secondcIndex
* @param forceSecondToZero
*/
void transfer(size_t faceIndex, size_t firstcIndex, size_t secondcIndex, bool forceSecondToZero = false) override
{
for(size_t i = 0; i < m_NumComps; i++)
{
m_FaceRef[faceIndex * m_NumComps + i] = m_CellRef[firstcIndex * m_NumComps + i];
}

if(!forceSecondToZero)
{
for(size_t i = 0; i < m_NumComps; i++)
{
m_FaceRef[faceIndex + i + m_NumComps] = m_CellRef[secondcIndex + i];
}
}
}
// void transfer(size_t faceIndex, size_t cellIndex1, size_t cellIndex2, bool forceSecondToZero) override
// {
// for(size_t i = 0; i < m_NumComps; i++)
// {
// m_FaceRef[faceIndex * m_NumComps + i] = m_CellRef[cellIndex1 * m_NumComps + i];
// }
//
// if(!forceSecondToZero)
// {
// for(size_t i = 0; i < m_NumComps; i++)
// {
// m_FaceRef[faceIndex * m_NumComps + i] = m_CellRef[cellIndex2 * m_NumComps + i];
// }
// }
// }

void transfer(size_t faceIndex, size_t firstcIndex) override
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ Parameters SurfaceNetsFilter::parameters() const
GeometrySelectionParameter::AllowedTypes{IGeometry::Type::Image}));
params.insert(std::make_unique<ArraySelectionParameter>(k_CellFeatureIdsArrayPath_Key, "Cell Feature Ids", "The complete path to the Array specifying which Feature each Cell belongs to", DataPath{},
ArraySelectionParameter::AllowedTypes{DataType::int32}, ArraySelectionParameter::AllowedComponentShapes{{1}}));
// params.insert(std::make_unique<MultiArraySelectionParameter>(
// k_SelectedDataArrayPaths_Key, "Attribute Arrays to Transfer", "The paths to the Arrays specifying which Cell Attribute Arrays to transfer to the created Triangle Geometry",
// MultiArraySelectionParameter::ValueType{}, MultiArraySelectionParameter::AllowedTypes{IArray::ArrayType::DataArray}, nx::core::GetAllDataTypes()));
params.insert(std::make_unique<MultiArraySelectionParameter>(
k_SelectedDataArrayPaths_Key, "Attribute Arrays to Transfer", "The paths to the Arrays specifying which Cell Attribute Arrays to transfer to the created Triangle Geometry",
MultiArraySelectionParameter::ValueType{}, MultiArraySelectionParameter::AllowedTypes{IArray::ArrayType::DataArray}, nx::core::GetAllDataTypes()));

params.insertSeparator(Parameters::Separator{"Output Triangle Geometry"});
params.insert(
Expand Down
Loading

0 comments on commit 5ef294a

Please sign in to comment.