// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkFitImplicitFunction.h" #include "vtkArrayDispatch.h" #include "vtkArrayDispatchDataSetArrayList.h" #include "vtkDataArrayRange.h" #include "vtkImplicitFunction.h" #include "vtkObjectFactory.h" #include "vtkPointSet.h" #include "vtkPoints.h" #include "vtkSMPTools.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkFitImplicitFunction); vtkCxxSetObjectMacro(vtkFitImplicitFunction, ImplicitFunction, vtkImplicitFunction); //------------------------------------------------------------------------------ // Helper classes to support efficient computing, and threaded execution. namespace { //------------------------------------------------------------------------------ // The threaded core of the algorithm template struct ExtractPointsFunctor { TArray* Points; vtkImplicitFunction* Function; double Threshold; vtkIdType* PointMap; ExtractPointsFunctor(TArray* points, vtkImplicitFunction* f, double thresh, vtkIdType* map) : Points(points) , Function(f) , Threshold(thresh) , PointMap(map) { } void operator()(vtkIdType ptId, vtkIdType endPtId) { auto p = vtk::DataArrayTupleRange<3>(this->Points, ptId).begin(); vtkIdType* map = this->PointMap + ptId; vtkImplicitFunction* f = this->Function; double x[3], val; double tMin = (-this->Threshold); double tMax = this->Threshold; for (; ptId < endPtId; ++ptId, ++p) { p->GetTuple(x); val = f->FunctionValue(x); *map++ = ((val >= tMin && val < tMax) ? 1 : -1); } } }; // ExtractPoints struct ExtractPointsWorker { template void operator()(TArray* inPts, vtkFitImplicitFunction* self, vtkIdType* pointMap) { ExtractPointsFunctor functor( inPts, self->GetImplicitFunction(), self->GetThreshold(), pointMap); vtkSMPTools::For(0, inPts->GetNumberOfTuples(), functor); } }; } // anonymous namespace //================= Begin class proper ======================================= //------------------------------------------------------------------------------ vtkFitImplicitFunction::vtkFitImplicitFunction() { this->ImplicitFunction = nullptr; this->Threshold = 0.01; } //------------------------------------------------------------------------------ vtkFitImplicitFunction::~vtkFitImplicitFunction() { this->SetImplicitFunction(nullptr); } //------------------------------------------------------------------------------ // Overload standard modified time function. If implicit function is modified, // then this object is modified as well. vtkMTimeType vtkFitImplicitFunction::GetMTime() { vtkMTimeType mTime = this->MTime.GetMTime(); vtkMTimeType impFuncMTime; if (this->ImplicitFunction != nullptr) { impFuncMTime = this->ImplicitFunction->GetMTime(); mTime = (impFuncMTime > mTime ? impFuncMTime : mTime); } return mTime; } //------------------------------------------------------------------------------ // Traverse all the input points and extract those that lie near the surface // of an implicit function. int vtkFitImplicitFunction::FilterPoints(vtkPointSet* input) { // Check the input. if (!this->ImplicitFunction) { vtkErrorMacro(<< "Implicit function required\n"); return 0; } // Determine which points, if any, should be removed. We create a map // to keep track. The bulk of the algorithmic work is done in this pass. ExtractPointsWorker worker; if (!vtkArrayDispatch::DispatchByArray::Execute( input->GetPoints()->GetData(), worker, this, this->PointMap)) { worker(input->GetPoints()->GetData(), this, this->PointMap); } return 1; } //------------------------------------------------------------------------------ void vtkFitImplicitFunction::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Implicit Function: " << static_cast(this->ImplicitFunction) << "\n"; os << indent << "Threshold: " << this->Threshold << "\n"; } VTK_ABI_NAMESPACE_END