/*========================================================================= Program: Visualization Toolkit Module: vtkImageToStructuredPoints.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 "vtkImageToStructuredPoints.h" #include "vtkCellData.h" #include "vtkDataArray.h" #include "vtkFieldData.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkStructuredPoints.h" #include vtkStandardNewMacro(vtkImageToStructuredPoints); //------------------------------------------------------------------------------ vtkImageToStructuredPoints::vtkImageToStructuredPoints() { this->SetNumberOfInputPorts(2); this->Translate[0] = this->Translate[1] = this->Translate[2] = 0; } //------------------------------------------------------------------------------ vtkImageToStructuredPoints::~vtkImageToStructuredPoints() = default; //------------------------------------------------------------------------------ void vtkImageToStructuredPoints::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } //------------------------------------------------------------------------------ vtkStructuredPoints* vtkImageToStructuredPoints::GetStructuredPointsOutput() { return vtkStructuredPoints::SafeDownCast(this->GetOutputDataObject(0)); } //------------------------------------------------------------------------------ void vtkImageToStructuredPoints::SetVectorInputData(vtkImageData* input) { this->SetInputData(1, input); } //------------------------------------------------------------------------------ vtkImageData* vtkImageToStructuredPoints::GetVectorInput() { if (this->GetNumberOfInputConnections(1) < 1) { return nullptr; } return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0)); } //------------------------------------------------------------------------------ int vtkImageToStructuredPoints::RequestData( vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkInformation* vectorInfo = inputVector[1]->GetInformationObject(0); vtkInformation* outInfo = outputVector->GetInformationObject(0); int uExtent[6]; int* wExtent; int idxX, idxY, idxZ; int maxX = 0; int maxY = 0; int maxZ = 0; vtkIdType inIncX, inIncY, inIncZ; int rowLength; unsigned char *inPtr1, *inPtr, *outPtr; vtkStructuredPoints* output = vtkStructuredPoints::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkImageData* data = vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); vtkImageData* vData = nullptr; if (vectorInfo) { vData = vtkImageData::SafeDownCast(vectorInfo->Get(vtkDataObject::DATA_OBJECT())); } outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent); output->SetExtent(uExtent); uExtent[0] += this->Translate[0]; uExtent[1] += this->Translate[0]; uExtent[2] += this->Translate[1]; uExtent[3] += this->Translate[1]; uExtent[4] += this->Translate[2]; uExtent[5] += this->Translate[2]; // if the data extent matches the update extent then just pass the data // otherwise we must reformat and copy the data if (data) { wExtent = data->GetExtent(); if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] && wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] && wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5]) { if (data->GetPointData()) { output->GetPointData()->PassData(data->GetPointData()); } if (data->GetCellData()) { output->GetCellData()->PassData(data->GetCellData()); } if (data->GetFieldData()) { output->GetFieldData()->ShallowCopy(data->GetFieldData()); } } else { inPtr = static_cast(data->GetScalarPointerForExtent(uExtent)); outPtr = static_cast(output->GetScalarPointer()); // Make sure there are data. if (!inPtr || !outPtr) { output->Initialize(); return 1; } // Get increments to march through data data->GetIncrements(inIncX, inIncY, inIncZ); // find the region to loop over rowLength = (uExtent[1] - uExtent[0] + 1) * inIncX * data->GetScalarSize(); maxX = uExtent[1] - uExtent[0]; maxY = uExtent[3] - uExtent[2]; maxZ = uExtent[5] - uExtent[4]; inIncY *= data->GetScalarSize(); inIncZ *= data->GetScalarSize(); // Loop through output pixels for (idxZ = 0; idxZ <= maxZ; idxZ++) { inPtr1 = inPtr + idxZ * inIncZ; for (idxY = 0; idxY <= maxY; idxY++) { memcpy(outPtr, inPtr1, rowLength); inPtr1 += inIncY; outPtr += rowLength; } } } } if (vData) { // if the data extent matches the update extent then just pass the data // otherwise we must reformat and copy the data wExtent = vData->GetExtent(); if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] && wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] && wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5]) { output->GetPointData()->SetVectors(vData->GetPointData()->GetScalars()); } else { vtkDataArray* fv = vtkDataArray::CreateDataArray(vData->GetScalarType()); float* inPtr2 = static_cast(vData->GetScalarPointerForExtent(uExtent)); // Make sure there are data. if (!inPtr2) { output->Initialize(); return 1; } fv->SetNumberOfComponents(3); fv->SetNumberOfTuples((maxZ + 1) * (maxY + 1) * (maxX + 1)); vData->GetContinuousIncrements(uExtent, inIncX, inIncY, inIncZ); int numComp = vData->GetNumberOfScalarComponents(); int idx = 0; // Loop through output pixels for (idxZ = 0; idxZ <= maxZ; idxZ++) { for (idxY = 0; idxY <= maxY; idxY++) { for (idxX = 0; idxX <= maxX; idxX++) { fv->SetTuple(idx, inPtr2); inPtr2 += numComp; idx++; } inPtr2 += inIncY; } inPtr2 += inIncZ; } output->GetPointData()->SetVectors(fv); fv->Delete(); } } return 1; } //------------------------------------------------------------------------------ // Copy WholeExtent, Spacing and Origin. int vtkImageToStructuredPoints::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // get the info objects vtkInformation* outInfo = outputVector->GetInformationObject(0); vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkInformation* vInfo = inputVector[1]->GetInformationObject(0); int whole[6], *tmp; double *spacing, origin[3]; vtkInformation* inScalarInfo = vtkDataObject::GetActiveFieldInformation( inInfo, vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); if (!inScalarInfo) { vtkErrorMacro("Missing scalar field on input information!"); return 0; } vtkDataObject::SetPointDataActiveScalarInfo(outInfo, inScalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()), inScalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS())); inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), whole); spacing = inInfo->Get(vtkDataObject::SPACING()); inInfo->Get(vtkDataObject::ORIGIN(), origin); // intersections for whole extent if (vInfo) { tmp = vInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); if (tmp[0] > whole[0]) { whole[0] = tmp[0]; } if (tmp[2] > whole[2]) { whole[2] = tmp[2]; } if (tmp[4] > whole[4]) { whole[4] = tmp[4]; } if (tmp[1] < whole[1]) { whole[1] = tmp[1]; } if (tmp[3] < whole[1]) { whole[3] = tmp[3]; } if (tmp[5] < whole[1]) { whole[5] = tmp[5]; } } // slide min extent to 0,0,0 (I Hate this !!!!) this->Translate[0] = whole[0]; this->Translate[1] = whole[2]; this->Translate[2] = whole[4]; origin[0] += spacing[0] * whole[0]; origin[1] += spacing[1] * whole[2]; origin[2] += spacing[2] * whole[4]; whole[1] -= whole[0]; whole[3] -= whole[2]; whole[5] -= whole[4]; whole[0] = whole[2] = whole[4] = 0; outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), whole, 6); // Now should Origin and Spacing really be part of information? // How about xyx arrays in RectilinearGrid of Points in StructuredGrid? outInfo->Set(vtkDataObject::ORIGIN(), origin, 3); outInfo->Set(vtkDataObject::SPACING(), spacing, 3); return 1; } //------------------------------------------------------------------------------ int vtkImageToStructuredPoints::RequestUpdateExtent( vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkInformation* vInfo = inputVector[1]->GetInformationObject(0); vtkInformation* outInfo = outputVector->GetInformationObject(0); int ext[6]; outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext); ext[0] += this->Translate[0]; ext[1] += this->Translate[0]; ext[2] += this->Translate[1]; ext[3] += this->Translate[1]; ext[4] += this->Translate[2]; ext[5] += this->Translate[2]; inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); if (vInfo) { vInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); } return 1; } //------------------------------------------------------------------------------ int vtkImageToStructuredPoints::FillOutputPortInformation(int port, vtkInformation* info) { if (!this->Superclass::FillOutputPortInformation(port, info)) { return 0; } info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredPoints"); return 1; } //------------------------------------------------------------------------------ int vtkImageToStructuredPoints::FillInputPortInformation(int port, vtkInformation* info) { if (!this->Superclass::FillInputPortInformation(port, info)) { return 0; } if (port == 1) { info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); } return 1; }