// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkExtractDataOverTime.h" #include "vtkDoubleArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPointSet.h" #include "vtkStreamingDemandDrivenPipeline.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkExtractDataOverTime); //------------------------------------------------------------------------------ vtkExtractDataOverTime::vtkExtractDataOverTime() { this->NumberOfTimeSteps = 0; this->CurrentTimeIndex = 0; this->PointIndex = 0; } //------------------------------------------------------------------------------ void vtkExtractDataOverTime::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Point Index: " << this->PointIndex << endl; os << indent << "NumberOfTimeSteps: " << this->NumberOfTimeSteps << endl; } //------------------------------------------------------------------------------ int vtkExtractDataOverTime::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); if (inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) { this->NumberOfTimeSteps = inInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); } else { this->NumberOfTimeSteps = 0; } // The output of this filter does not contain a specific time, rather // it contains a collection of time steps. Also, this filter does not // respond to time requests. Therefore, we remove all time information // from the output. vtkInformation* outInfo = outputVector->GetInformationObject(0); if (outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) { outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); } if (outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE())) { outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE()); } return 1; } //------------------------------------------------------------------------------ vtkTypeBool vtkExtractDataOverTime::ProcessRequest( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { if (request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) { return this->RequestInformation(request, inputVector, outputVector); } else if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) { // get the requested update extent double* inTimes = inputVector[0]->GetInformationObject(0)->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); if (inTimes) { double timeReq = inTimes[this->CurrentTimeIndex]; inputVector[0]->GetInformationObject(0)->Set( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP(), timeReq); } return 1; } // generate the data else if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) { if (this->NumberOfTimeSteps == 0) { vtkErrorMacro("No Time steps in input time data!"); return 0; } // get the output data object vtkInformation* outInfo = outputVector->GetInformationObject(0); vtkPointSet* output = vtkPointSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // and input data object vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkPointSet* input = vtkPointSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); // is this the first request if (!this->CurrentTimeIndex) { // Tell the pipeline to start looping. request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); this->AllocateOutputData(input, output); } // extract the actual data output->GetPoints()->SetPoint( this->CurrentTimeIndex, input->GetPoints()->GetPoint(this->PointIndex)); output->GetPointData()->CopyData( input->GetPointData(), this->PointIndex, this->CurrentTimeIndex); if (input->GetPointData()->GetArray("Time")) { output->GetPointData() ->GetArray("TimeData") ->SetTuple1( this->CurrentTimeIndex, input->GetInformation()->Get(vtkDataObject::DATA_TIME_STEP())); } else { output->GetPointData()->GetArray("Time")->SetTuple1( this->CurrentTimeIndex, input->GetInformation()->Get(vtkDataObject::DATA_TIME_STEP())); } // increment the time index this->CurrentTimeIndex++; if (this->CheckAbort() || this->CurrentTimeIndex == this->NumberOfTimeSteps) { // Tell the pipeline to stop looping. request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); this->CurrentTimeIndex = 0; } return 1; } return this->Superclass::ProcessRequest(request, inputVector, outputVector); } //------------------------------------------------------------------------------ int vtkExtractDataOverTime::AllocateOutputData(vtkPointSet* input, vtkPointSet* output) { // by default vtkPointSetAlgorithm::RequestDataObject already // created an output of the same type as the input if (!output) { vtkErrorMacro("Output not created as expected!"); return 0; } // 1st the points vtkPoints* points = output->GetPoints(); if (!points) { points = vtkPoints::New(); output->SetPoints(points); points->Delete(); } points->SetNumberOfPoints(this->NumberOfTimeSteps); // now the point data output->GetPointData()->CopyAllocate(input->GetPointData(), this->NumberOfTimeSteps); // and finally add an array to hold the time at each step vtkDoubleArray* timeArray = vtkDoubleArray::New(); timeArray->SetNumberOfComponents(1); timeArray->SetNumberOfTuples(this->NumberOfTimeSteps); if (input->GetPointData()->GetArray("Time")) { timeArray->SetName("TimeData"); } else { timeArray->SetName("Time"); } output->GetPointData()->AddArray(timeArray); timeArray->Delete(); return 1; } VTK_ABI_NAMESPACE_END