vtk-m/vtkm/filter/SurfaceNormals.hxx
Kenneth Moreland be7f06bbe7 CoordinateSystem data is VariantArrayHandle
`CoordinateSystem` differed from `Field` in that its `GetData`
method returned an `ArrayHandleVirtualCoordinates` instead of
a `VariantArrayHandle`. This is probably confusing since
`CoordianteSystem` inherits `Field` and has a pretty dramatic
difference in this behavior.

In preparation to deprecate `ArrayHandleVirtualCoordinates`, this
changes `CoordiantSystem` to be much more like `Field`. (In the
future, we may change the `CoordinateSystem` to point to a `Field`
rather than be a special `Field`.)

A method named `GetDataAsMultiplexer` has been added to
`CoordinateSystem`. This method allows you to get data from
`CoordinateSystem` as a single array type without worrying
about creating functors to handle different types and without
needing virtual methods.
2020-07-14 08:50:39 -06:00

157 lines
4.1 KiB
C++

//============================================================================
// 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_SurfaceNormals_hxx
#define vtk_m_filter_SurfaceNormals_hxx
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/worklet/OrientNormals.h>
#include <vtkm/worklet/SurfaceNormals.h>
#include <vtkm/worklet/TriangleWinding.h>
namespace vtkm
{
namespace filter
{
namespace internal
{
inline std::string ComputePointNormalsName(const SurfaceNormals* filter)
{
if (!filter->GetPointNormalsName().empty())
{
return filter->GetPointNormalsName();
}
else if (!filter->GetOutputFieldName().empty())
{
return filter->GetOutputFieldName();
}
else
{
return "Normals";
}
}
inline std::string ComputeCellNormalsName(const SurfaceNormals* filter)
{
if (!filter->GetCellNormalsName().empty())
{
return filter->GetCellNormalsName();
}
else if (!filter->GetGeneratePointNormals() && !filter->GetOutputFieldName().empty())
{
return filter->GetOutputFieldName();
}
else
{
return "Normals";
}
}
} // internal
inline SurfaceNormals::SurfaceNormals()
: GenerateCellNormals(false)
, NormalizeCellNormals(true)
, GeneratePointNormals(true)
, AutoOrientNormals(false)
, FlipNormals(false)
, Consistency(true)
{
this->SetUseCoordinateSystemAsField(true);
}
template <typename T, typename StorageType, typename DerivedPolicy>
inline vtkm::cont::DataSet SurfaceNormals::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& points,
const vtkm::filter::FieldMetadata& fieldMeta,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
VTKM_ASSERT(fieldMeta.IsPointField());
if (!this->GenerateCellNormals && !this->GeneratePointNormals)
{
throw vtkm::cont::ErrorFilterExecution("No normals selected.");
}
const auto cellset =
vtkm::filter::ApplyPolicyCellSetUnstructured(input.GetCellSet(), policy, *this);
const auto coords =
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()).GetDataAsMultiplexer();
vtkm::cont::ArrayHandle<vtkm::Vec3f> faceNormals;
vtkm::worklet::FacetedSurfaceNormals faceted;
faceted.SetNormalize(this->NormalizeCellNormals);
faceted.Run(cellset, points, faceNormals);
vtkm::cont::DataSet result;
vtkm::cont::ArrayHandle<vtkm::Vec3f> pointNormals;
if (this->GeneratePointNormals)
{
vtkm::worklet::SmoothSurfaceNormals smooth;
smooth.Run(cellset, faceNormals, pointNormals);
result = CreateResultFieldPoint(input, pointNormals, internal::ComputePointNormalsName(this));
if (this->GenerateCellNormals)
{
result.AddField(
vtkm::cont::make_FieldCell(internal::ComputeCellNormalsName(this), faceNormals));
}
}
else
{
result = CreateResultFieldCell(input, faceNormals, internal::ComputeCellNormalsName(this));
}
if (this->AutoOrientNormals)
{
using Orient = vtkm::worklet::OrientNormals;
if (this->GenerateCellNormals && this->GeneratePointNormals)
{
Orient::RunPointAndCellNormals(cellset, coords, pointNormals, faceNormals);
}
else if (this->GenerateCellNormals)
{
Orient::RunCellNormals(cellset, coords, faceNormals);
}
else if (this->GeneratePointNormals)
{
Orient::RunPointNormals(cellset, coords, pointNormals);
}
if (this->FlipNormals)
{
if (this->GenerateCellNormals)
{
Orient::RunFlipNormals(faceNormals);
}
if (this->GeneratePointNormals)
{
Orient::RunFlipNormals(pointNormals);
}
}
}
if (this->Consistency && this->GenerateCellNormals)
{
auto newCells = vtkm::worklet::TriangleWinding::Run(cellset, coords, faceNormals);
result.SetCellSet(newCells); // Overwrite the cellset in the result
}
return result;
}
}
} // vtkm::filter
#endif