// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkSynchronizeTimeFilter.h" #include "vtkDataObject.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkStreamingDemandDrivenPipeline.h" #include #include VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkSynchronizeTimeFilter); //------------------------------------------------------------------------------ void vtkSynchronizeTimeFilter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "RelativeTolerance: " << this->RelativeTolerance << endl; } //------------------------------------------------------------------------------ vtkSynchronizeTimeFilter::vtkSynchronizeTimeFilter() { this->SetNumberOfInputPorts(2); this->RelativeTolerance = 0.00001; } //------------------------------------------------------------------------------ vtkSynchronizeTimeFilter::~vtkSynchronizeTimeFilter() = default; //------------------------------------------------------------------------------ void vtkSynchronizeTimeFilter::SetSourceConnection(vtkAlgorithmOutput* algOutput) { this->SetInputConnection(1, algOutput); } //------------------------------------------------------------------------------ double vtkSynchronizeTimeFilter::GetInputTimeValue(double outputTimeValue) { double inputTimeValue = outputTimeValue; if (outputTimeValue <= this->OutputTimeStepValues.back()) { std::vector::iterator pos = std::find( this->OutputTimeStepValues.begin(), this->OutputTimeStepValues.end(), outputTimeValue); if (pos != this->OutputTimeStepValues.end()) { size_t index = std::distance(this->OutputTimeStepValues.begin(), pos); inputTimeValue = this->InputTimeStepValues[index]; } } return inputTimeValue; } //------------------------------------------------------------------------------ double vtkSynchronizeTimeFilter::GetOutputTimeValue(double inputTimeValue) { double outputTimeValue = inputTimeValue; std::vector::iterator pos = std::find(this->InputTimeStepValues.begin(), this->InputTimeStepValues.end(), inputTimeValue); if (pos != this->InputTimeStepValues.end()) { size_t index = std::distance(this->InputTimeStepValues.begin(), pos); if (index < this->OutputTimeStepValues.size()) { outputTimeValue = this->OutputTimeStepValues[index]; } } return outputTimeValue; } //------------------------------------------------------------------------------ int vtkSynchronizeTimeFilter::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { this->InputTimeStepValues.clear(); this->OutputTimeStepValues.clear(); vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); if (inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) { int numberOfTimeSteps = inInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); double* values = inInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); this->InputTimeStepValues.resize(numberOfTimeSteps); this->OutputTimeStepValues.resize(numberOfTimeSteps); for (int i = 0; i < numberOfTimeSteps; i++) { this->InputTimeStepValues[i] = values[i]; this->OutputTimeStepValues[i] = values[i]; } // time steps for port 1 (sync time steps) inInfo = inputVector[1]->GetInformationObject(0); if (inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) { int numberOfOutputTimeSteps = inInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); values = inInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); double diffMax = this->RelativeTolerance * std::abs(this->InputTimeStepValues[0] - this->InputTimeStepValues[numberOfTimeSteps - 1]); for (int i = 0; i < numberOfOutputTimeSteps; i++) { for (size_t j = 0; j < this->OutputTimeStepValues.size(); j++) { if (std::abs(values[i] - this->OutputTimeStepValues[j]) < diffMax) { this->OutputTimeStepValues[j] = values[i]; } } } } // check to make sure we don't have any repeated time steps for (size_t i = 0; i < this->OutputTimeStepValues.size() - 1; i++) { if (this->OutputTimeStepValues[i] == this->OutputTimeStepValues[i + 1]) { vtkWarningMacro("The Synchronize Time Filter detected 2 time steps that " << "mapped to the same value. Either the input data has " << "2 time steps with identical time values or the " << "RelativeTolerance parameter (currently set to " << this->RelativeTolerance << ") is too large"); } } vtkInformation* outInfo = outputVector->GetInformationObject(0); double timeRange[2] = { this->OutputTimeStepValues[0], this->OutputTimeStepValues[numberOfTimeSteps - 1] }; outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->OutputTimeStepValues.data(), numberOfTimeSteps); outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2); } else { // just in case output time steps are set by the second input vtkInformation* outInfo = outputVector->GetInformationObject(0); outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE()); } return 1; } //------------------------------------------------------------------------------ int vtkSynchronizeTimeFilter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkInformation* outInfo = outputVector->GetInformationObject(0); if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP())) { double timeValue = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); double requestTimeValue = this->GetInputTimeValue(timeValue); inputVector[0]->GetInformationObject(0)->Set( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP(), requestTimeValue); } else { inputVector[0]->GetInformationObject(0)->Remove( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); } // Always remove the request for the update time step from // the sync input since we only care about the time step values // that it can provide and we already have that. inputVector[1]->GetInformationObject(0)->Remove( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); return 1; } //------------------------------------------------------------------------------ int vtkSynchronizeTimeFilter::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkInformation* outInfo = outputVector->GetInformationObject(0); vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT()); vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT()); output->ShallowCopy(input); if (input->GetInformation()->Has(vtkDataObject::DATA_TIME_STEP())) { double timeValue = input->GetInformation()->Get(vtkDataObject::DATA_TIME_STEP()); double outputTimeValue = this->GetOutputTimeValue(timeValue); output->GetInformation()->Set(vtkDataObject::DATA_TIME_STEP(), outputTimeValue); } this->CheckAbort(); return 1; } VTK_ABI_NAMESPACE_END