/*========================================================================= Program: Visualization Toolkit Module: vtkImageToPoints.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImageToPoints.h" #include #include #include #include #include #include #include #include #include #include #include #include vtkStandardNewMacro(vtkImageToPoints); //------------------------------------------------------------------------------ // Constructor sets default values vtkImageToPoints::vtkImageToPoints() { this->OutputPointsPrecision = vtkAlgorithm::DEFAULT_PRECISION; this->SetNumberOfInputPorts(2); this->SetNumberOfOutputPorts(1); } //------------------------------------------------------------------------------ vtkImageToPoints::~vtkImageToPoints() = default; //------------------------------------------------------------------------------ void vtkImageToPoints::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "OutputPointsPrecision: " << this->OutputPointsPrecision << "\n"; } //------------------------------------------------------------------------------ void vtkImageToPoints::SetStencilConnection(vtkAlgorithmOutput* stencil) { this->SetInputConnection(1, stencil); } //------------------------------------------------------------------------------ vtkAlgorithmOutput* vtkImageToPoints::GetStencilConnection() { return this->GetInputConnection(1, 0); } //------------------------------------------------------------------------------ void vtkImageToPoints::SetStencilData(vtkImageStencilData* stencil) { this->SetInputData(1, stencil); } //------------------------------------------------------------------------------ int vtkImageToPoints::FillInputPortInformation(int port, vtkInformation* info) { if (port == 0) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); } else if (port == 1) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData"); info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); } return 1; } //------------------------------------------------------------------------------ int vtkImageToPoints::FillOutputPortInformation(int port, vtkInformation* info) { if (port == 0) { info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData"); } return 1; } //------------------------------------------------------------------------------ int vtkImageToPoints::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* vtkNotUsed(outputVector)) { return 1; } //------------------------------------------------------------------------------ int vtkImageToPoints::RequestUpdateExtent(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector)) { int inExt[6]; vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt); inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); // need to set the stencil update extent to the input extent if (this->GetNumberOfInputConnections(1) > 0) { vtkInformation* stencilInfo = inputVector[1]->GetInformationObject(0); stencilInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); } return 1; } namespace { //------------------------------------------------------------------------------ vtkIdType vtkImageToPointsCount( vtkImageData* inData, vtkImageStencilData* stencil, const int extent[6]) { // count the number of points so that we can pre-allocate the space vtkIdType count = 0; // iterate over all spans for the stencil vtkImagePointDataIterator inIter(inData, extent, stencil); for (; !inIter.IsAtEnd(); inIter.NextSpan()) { if (inIter.IsInStencil()) { count += inIter.SpanEndId() - inIter.GetId(); } } return count; } //------------------------------------------------------------------------------ // The execute method is templated over the point type (float or double) template void vtkImageToPointsExecute(vtkImageToPoints* self, vtkImageData* inData, const int extent[6], vtkImageStencilData* stencil, T* outPoints, vtkPointData* outPD) { vtkPointData* inPD = inData->GetPointData(); vtkImagePointIterator inIter(inData, extent, stencil, self, 0); vtkIdType outId = 0; // iterate over all spans for the stencil while (!inIter.IsAtEnd()) { if (inIter.IsInStencil()) { // if span is inside stencil, generate points vtkIdType n = inIter.SpanEndId() - inIter.GetId(); outPD->CopyData(inPD, outId, n, inIter.GetId()); outId += n; for (vtkIdType i = 0; i < n; i++) { inIter.GetPosition(outPoints); outPoints += 3; inIter.Next(); } } else { // if span is outside stencil, skip to next span inIter.NextSpan(); } } } } //------------------------------------------------------------------------------ int vtkImageToPoints::RequestData( vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // get the input vtkInformation* info = inputVector[0]->GetInformationObject(0); vtkInformation* stencilInfo = inputVector[1]->GetInformationObject(0); vtkImageData* inData = vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT())); // use a stencil, if a stencil is connected vtkImageStencilData* stencil = nullptr; if (stencilInfo) { stencil = static_cast(stencilInfo->Get(vtkDataObject::DATA_OBJECT())); } // get the requested precision int pointsType = VTK_DOUBLE; if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION) { pointsType = VTK_FLOAT; } // get the output data object vtkInformation* outInfo = outputVector->GetInformationObject(0); vtkPolyData* outData = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // count the total number of output points const int* extent = inData->GetExtent(); vtkIdType numPoints = vtkImageToPointsCount(inData, stencil, extent); // create the points vtkSmartPointer points = vtkSmartPointer::New(); points->SetDataType(pointsType); points->SetNumberOfPoints(numPoints); outData->SetPoints(points); // pre-allocate output arrays vtkPointData* outPD = outData->GetPointData(); outPD->CopyAllocate(inData->GetPointData(), numPoints); // iterate over the input and create the point data void* ptr = points->GetVoidPointer(0); if (pointsType == VTK_FLOAT) { vtkImageToPointsExecute(this, inData, extent, stencil, static_cast(ptr), outPD); } else { vtkImageToPointsExecute(this, inData, extent, stencil, static_cast(ptr), outPD); } return 1; }