mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-08 11:29:02 +00:00
Add a ConvertToPointCloud filter
This filter takes a `DataSet` and returns a point cloud representation that has a vertex cell associated with each point in it. This is useful for filling in a `CellSet` for data that has points but no cells. It is also useful for operations in which you want to throw away the cell geometry and operate on the data as a collection of disparate points.
This commit is contained in:
parent
99c548ef52
commit
8b6c5250d2
7
docs/changelog/convert-to-point-cloud.md
Normal file
7
docs/changelog/convert-to-point-cloud.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Added a `ConvertToPointCloud` filter
|
||||
|
||||
This filter takes a `DataSet` and returns a point cloud representation that
|
||||
has a vertex cell associated with each point in it. This is useful for
|
||||
filling in a `CellSet` for data that has points but no cells. It is also
|
||||
useful for operations in which you want to throw away the cell geometry and
|
||||
operate on the data as a collection of disparate points.
|
@ -8,6 +8,7 @@
|
||||
## PURPOSE. See the above copyright notice for more information.
|
||||
##============================================================================
|
||||
set(geometry_refinement_headers
|
||||
ConvertToPointCloud.h
|
||||
Shrink.h
|
||||
SplitSharpEdges.h
|
||||
Tetrahedralize.h
|
||||
@ -17,6 +18,7 @@ set(geometry_refinement_headers
|
||||
)
|
||||
|
||||
set(geometry_refinement_sources
|
||||
ConvertToPointCloud.cxx
|
||||
Shrink.cxx
|
||||
SplitSharpEdges.cxx
|
||||
Tetrahedralize.cxx
|
||||
|
61
vtkm/filter/geometry_refinement/ConvertToPointCloud.cxx
Normal file
61
vtkm/filter/geometry_refinement/ConvertToPointCloud.cxx
Normal file
@ -0,0 +1,61 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/filter/geometry_refinement/ConvertToPointCloud.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/CellSetSingleType.h>
|
||||
|
||||
#include <vtkm/CellShape.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace geometry_refinement
|
||||
{
|
||||
|
||||
vtkm::cont::DataSet ConvertToPointCloud::DoExecute(const vtkm::cont::DataSet& input)
|
||||
{
|
||||
vtkm::Id numPoints = input.GetNumberOfPoints();
|
||||
|
||||
// A connectivity array for a point cloud is easy. All the cells are a vertex with exactly
|
||||
// one point. So, it can be represented a simple index array (i.e., 0, 1, 2, 3, ...).
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex{ numPoints }, connectivity);
|
||||
|
||||
vtkm::cont::CellSetSingleType<> cellSet;
|
||||
cellSet.Fill(numPoints, vtkm::CELL_SHAPE_VERTEX, 1, connectivity);
|
||||
|
||||
auto fieldMapper = [&](vtkm::cont::DataSet& outData, vtkm::cont::Field& field) {
|
||||
if (field.IsCellField())
|
||||
{
|
||||
// Cell fields are dropped.
|
||||
return;
|
||||
}
|
||||
else if (this->AssociateFieldsWithCells && field.IsPointField() &&
|
||||
!input.HasCoordinateSystem(field.GetName()))
|
||||
{
|
||||
// The user asked to convert point fields to cell fields. (They are interchangable in
|
||||
// point clouds.)
|
||||
outData.AddCellField(field.GetName(), field.GetData());
|
||||
}
|
||||
else
|
||||
{
|
||||
outData.AddField(field);
|
||||
}
|
||||
};
|
||||
return this->CreateResult(input, cellSet, fieldMapper);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::filter::geometry_refinement
|
64
vtkm/filter/geometry_refinement/ConvertToPointCloud.h
Normal file
64
vtkm/filter/geometry_refinement/ConvertToPointCloud.h
Normal file
@ -0,0 +1,64 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#ifndef vtk_m_filter_geometry_refinement_ConvertToPointCloud_h
|
||||
#define vtk_m_filter_geometry_refinement_ConvertToPointCloud_h
|
||||
|
||||
#include <vtkm/filter/Filter.h>
|
||||
#include <vtkm/filter/geometry_refinement/vtkm_filter_geometry_refinement_export.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace geometry_refinement
|
||||
{
|
||||
|
||||
/// \brief Convert a `DataSet` to a point cloud.
|
||||
///
|
||||
/// A point cloud in VTK-m is represented as a data set with "vertex" shape cells.
|
||||
/// This filter replaces the `CellSet` in a `DataSet` with a `CellSet` of only
|
||||
/// vertex cells. There will be one cell per point.
|
||||
///
|
||||
/// This filter is useful for dropping the cells of any `DataSet` so that you can
|
||||
/// operate on it as just a collection of points. It is also handy for completing
|
||||
/// a `DataSet` that does not have a `CellSet` associated with it or has points
|
||||
/// that do not belong to cells.
|
||||
///
|
||||
/// Note that all fields associated with cells are dropped. This is because the
|
||||
/// cells are dropped.
|
||||
///
|
||||
class VTKM_FILTER_GEOMETRY_REFINEMENT_EXPORT ConvertToPointCloud : public vtkm::filter::Filter
|
||||
{
|
||||
bool AssociateFieldsWithCells = false;
|
||||
|
||||
public:
|
||||
///@{
|
||||
/// By default, all the input point fields are kept as point fields in the output.
|
||||
/// However, the output has exactly one cell per point and it might be easier to
|
||||
/// treat the fields as cell fields. When this flag is turned on, the point field
|
||||
/// association is changed to cell.
|
||||
///
|
||||
/// Note that any field that is marked as point coordinates will remain as point
|
||||
/// fields. It is not valid to set a cell field as the point coordinates.
|
||||
///
|
||||
VTKM_CONT void SetAssociateFieldsWithCells(bool flag) { this->AssociateFieldsWithCells = flag; }
|
||||
VTKM_CONT bool GetAssociateFieldsWithCells() const { return this->AssociateFieldsWithCells; }
|
||||
///@}
|
||||
|
||||
protected:
|
||||
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::filter::geometry_refinement
|
||||
|
||||
#endif //vtk_m_filter_geometry_refinement_ConvertToPointCloud_h
|
@ -9,6 +9,7 @@
|
||||
##============================================================================
|
||||
|
||||
set(unit_tests
|
||||
UnitTestConvertToPointCloud.cxx
|
||||
UnitTestShrinkFilter.cxx
|
||||
UnitTestSplitSharpEdgesFilter.cxx
|
||||
UnitTestTetrahedralizeFilter.cxx
|
||||
|
@ -0,0 +1,135 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/filter/geometry_refinement/ConvertToPointCloud.h>
|
||||
|
||||
#include <vtkm/io/VTKDataSetReader.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void CheckPointCloudCells(const vtkm::cont::UnknownCellSet& cellSet, vtkm::Id numPoints)
|
||||
{
|
||||
// A point cloud has the same number of cells as points. All cells are vertex
|
||||
// cells with one point. That point index is the same as the cell index.
|
||||
|
||||
VTKM_TEST_ASSERT(cellSet.GetNumberOfPoints() == numPoints);
|
||||
VTKM_TEST_ASSERT(cellSet.GetNumberOfCells() == numPoints);
|
||||
|
||||
for (vtkm::Id index = 0; index < numPoints; ++index)
|
||||
{
|
||||
VTKM_TEST_ASSERT(cellSet.GetCellShape(index) == vtkm::CELL_SHAPE_VERTEX);
|
||||
VTKM_TEST_ASSERT(cellSet.GetNumberOfPointsInCell(index) == 1);
|
||||
|
||||
vtkm::Id pointId;
|
||||
cellSet.GetCellPointIds(index, &pointId);
|
||||
VTKM_TEST_ASSERT(pointId == index);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckPointCloudCells(const vtkm::cont::DataSet& dataSet, vtkm::Id numPoints)
|
||||
{
|
||||
CheckPointCloudCells(dataSet.GetCellSet(), numPoints);
|
||||
}
|
||||
|
||||
void TryConvertToPointCloud(const vtkm::cont::DataSet& dataSet)
|
||||
{
|
||||
{
|
||||
std::cout << " convert to point cloud" << std::endl;
|
||||
vtkm::filter::geometry_refinement::ConvertToPointCloud convertFilter;
|
||||
vtkm::cont::DataSet pointCloud = convertFilter.Execute(dataSet);
|
||||
CheckPointCloudCells(pointCloud, dataSet.GetNumberOfPoints());
|
||||
|
||||
for (vtkm::IdComponent coordId = 0; coordId < dataSet.GetNumberOfCoordinateSystems(); ++coordId)
|
||||
{
|
||||
const auto& coords = dataSet.GetCoordinateSystem(coordId);
|
||||
std::cout << " coord system " << coords.GetName() << std::endl;
|
||||
VTKM_TEST_ASSERT(pointCloud.HasCoordinateSystem(coords.GetName()));
|
||||
}
|
||||
|
||||
for (vtkm::IdComponent fieldId = 0; fieldId < dataSet.GetNumberOfFields(); ++fieldId)
|
||||
{
|
||||
const auto& field = dataSet.GetField(fieldId);
|
||||
std::cout << " field " << field.GetName() << std::endl;
|
||||
switch (field.GetAssociation())
|
||||
{
|
||||
case vtkm::cont::Field::Association::Cells:
|
||||
VTKM_TEST_ASSERT(!pointCloud.HasField(field.GetName()));
|
||||
break;
|
||||
default:
|
||||
VTKM_TEST_ASSERT(pointCloud.HasField(field.GetName(), field.GetAssociation()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << " convert to point cloud with cell data" << std::endl;
|
||||
vtkm::filter::geometry_refinement::ConvertToPointCloud convertFilter;
|
||||
convertFilter.SetAssociateFieldsWithCells(true);
|
||||
vtkm::cont::DataSet pointCloud = convertFilter.Execute(dataSet);
|
||||
CheckPointCloudCells(pointCloud, dataSet.GetNumberOfPoints());
|
||||
|
||||
for (vtkm::IdComponent coordId = 0; coordId < dataSet.GetNumberOfCoordinateSystems(); ++coordId)
|
||||
{
|
||||
const auto& coords = dataSet.GetCoordinateSystem(coordId);
|
||||
std::cout << " coord system " << coords.GetName() << std::endl;
|
||||
VTKM_TEST_ASSERT(pointCloud.HasCoordinateSystem(coords.GetName()));
|
||||
}
|
||||
|
||||
for (vtkm::IdComponent fieldId = 0; fieldId < dataSet.GetNumberOfFields(); ++fieldId)
|
||||
{
|
||||
auto& field = dataSet.GetField(fieldId);
|
||||
std::cout << " field " << field.GetName() << std::endl;
|
||||
switch (field.GetAssociation())
|
||||
{
|
||||
case vtkm::cont::Field::Association::Cells:
|
||||
VTKM_TEST_ASSERT(!pointCloud.HasField(field.GetName()));
|
||||
break;
|
||||
case vtkm::cont::Field::Association::Points:
|
||||
{
|
||||
auto correctAssociation = dataSet.HasCoordinateSystem(field.GetName())
|
||||
? vtkm::cont::Field::Association::Points
|
||||
: vtkm::cont::Field::Association::Cells;
|
||||
VTKM_TEST_ASSERT(pointCloud.HasField(field.GetName(), correctAssociation));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
VTKM_TEST_ASSERT(pointCloud.HasField(field.GetName(), field.GetAssociation()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TryFile(const std::string& filename)
|
||||
{
|
||||
std::cout << "Testing " << filename << std::endl;
|
||||
std::string fullpath = vtkm::cont::testing::Testing::DataPath(filename);
|
||||
vtkm::io::VTKDataSetReader reader(fullpath);
|
||||
TryConvertToPointCloud(reader.ReadDataSet());
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
TryFile("uniform/simple_structured_points_bin.vtk");
|
||||
TryFile("rectilinear/DoubleGyre_0.vtk");
|
||||
TryFile("curvilinear/kitchen.vtk");
|
||||
TryFile("unstructured/simple_unstructured_bin.vtk");
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestConvertToPointCloud(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
|
||||
}
|
@ -12,6 +12,7 @@ TEST_DEPENDS
|
||||
vtkm_filter_field_conversion
|
||||
vtkm_filter_geometry_refinement
|
||||
vtkm_filter_vector_analysis
|
||||
vtkm_io
|
||||
vtkm_source
|
||||
TEST_OPTIONAL_DEPENDS
|
||||
vtkm_rendering_testing
|
||||
|
Loading…
Reference in New Issue
Block a user