// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkTimeSourceExample.h" #include "vtkAlgorithm.h" #include "vtkCellData.h" #include "vtkCellType.h" #include "vtkDoubleArray.h" #include "vtkIdTypeArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPoints.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkUnstructuredGrid.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkTimeSourceExample); //------------------------------------------------------------------------------ double vtkTimeSourceExample::ValueFunction(double t) { return sin(2 * vtkMath::Pi() * t); } //------------------------------------------------------------------------------ double vtkTimeSourceExample::XFunction(double t) { return sin(2 * vtkMath::Pi() * t) * this->XAmplitude; } //------------------------------------------------------------------------------ double vtkTimeSourceExample::YFunction(double t) { return sin(2 * vtkMath::Pi() * t) * this->YAmplitude; } //------------------------------------------------------------------------------ void vtkTimeSourceExample::LookupTimeAndValue(double& time, double& value) { double t = time; if (this->Analytic) { time = t; // clamp within range time = std::max(time, this->Steps[0]); time = std::min(time, this->Steps[this->NumSteps - 1]); value = this->ValueFunction(time); } else { int index = -2; for (int i = 0; i < this->NumSteps; i++) { if (this->Steps[i] == t) { index = i; break; } if (this->Steps[i] > t) { index = i - 1; break; } } if (index == -1) { index = 0; } if (index == -2) { index = this->NumSteps - 1; } time = this->Steps[index]; value = this->Values[index]; } } //------------------------------------------------------------------------------ int vtkTimeSourceExample::NumCellsFunction(double t) { int numCells = 1; if (this->Growing) { // goes from 1 to NumSteps/2+1, adding one cell each step, and returns double halfSteps = this->NumSteps / 2.0; numCells = (int)(halfSteps - (fabs(2.0 * (t - 0.5) * halfSteps))); numCells += 1; } return numCells; } //------------------------------------------------------------------------------ vtkTimeSourceExample::vtkTimeSourceExample() { this->SetNumberOfInputPorts(0); this->Analytic = 0; this->XAmplitude = 0.0; this->YAmplitude = 0.0; this->Growing = 0; this->NumSteps = 10; // times are regularly sampled from 0.0 to 1.0 this->Steps = new double[this->NumSteps]; for (int i = 0; i < this->NumSteps; i++) { this->Steps[i] = (double)i / (double)(this->NumSteps - 1); } // create the table of values at those times for usee when acting as discrete this->Values = new double[this->NumSteps]; for (int i = 0; i < this->NumSteps; i++) { this->Values[i] = this->ValueFunction((double)i / (double)(this->NumSteps - 1)); } } //------------------------------------------------------------------------------ vtkTimeSourceExample::~vtkTimeSourceExample() { delete[] this->Steps; delete[] this->Values; } //------------------------------------------------------------------------------ int vtkTimeSourceExample::RequestInformation( vtkInformation* reqInfo, vtkInformationVector** inVector, vtkInformationVector* outVector) { if (!this->Superclass::RequestInformation(reqInfo, inVector, outVector)) { return 0; } vtkInformation* info = outVector->GetInformationObject(0); // tell the caller that I can provide time varying data and // tell it what range of times I can deal with double tRange[2]; tRange[0] = this->Steps[0]; tRange[1] = this->Steps[this->NumSteps - 1]; info->Set(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), tRange, 2); // tell the caller if this filter can provide values ONLY at discrete times // or anywhere within the time range if (!this->Analytic) { info->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps, this->NumSteps); } else { info->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); } info->Set(CAN_HANDLE_PIECE_REQUEST(), 1); return 1; } //------------------------------------------------------------------------------ int vtkTimeSourceExample::RequestData(vtkInformation* vtkNotUsed(reqInfo), vtkInformationVector** vtkNotUsed(inVector), vtkInformationVector* outVector) { vtkInformation* outInfo = outVector->GetInformationObject(0); vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); if (!output) { return 0; } // determine what time is being asked for double reqTime = 0.0; // int reqNTS = 0; double reqTS(0); if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP())) { // reqNTS = outInfo->Length // (vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); reqTS = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); // TODO: produce multiblock output when multiple time steps are asked for // for now just answer the first one reqTime = reqTS; } // if analytic compute the value at that time // if discrete look up the nearest time and value from the table double time = reqTime; double value = 0.0; this->LookupTimeAndValue(time, value); output->Initialize(); output->GetInformation()->Set(vtkDataObject::DATA_TIME_STEP(), time); // figure out the world space position of the output double x = this->XFunction(time); double y = this->YFunction(time); // figure out the number of cells in the output int numCells = this->NumCellsFunction(time); // compute values for each point and cell to test with vtkDoubleArray* pd = vtkDoubleArray::New(); pd->SetNumberOfComponents(1); pd->SetName("Point Value"); output->GetPointData()->AddArray(pd); vtkIdTypeArray* id = vtkIdTypeArray::New(); id->SetNumberOfComponents(1); id->SetName("Point Label"); output->GetPointData()->AddArray(id); output->GetPointData()->SetGlobalIds(id); vtkDoubleArray* xd = vtkDoubleArray::New(); xd->SetNumberOfComponents(1); xd->SetName("Point X"); output->GetPointData()->AddArray(xd); vtkDoubleArray* yd = vtkDoubleArray::New(); yd->SetNumberOfComponents(1); yd->SetName("Point Y"); output->GetPointData()->AddArray(yd); vtkDoubleArray* zd = vtkDoubleArray::New(); zd->SetNumberOfComponents(1); zd->SetName("Point Z"); output->GetPointData()->AddArray(zd); vtkPoints* points = vtkPoints::New(); vtkIdType pid = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < numCells + 1; j++) { if (this->CheckAbort()) { break; } for (int k = 0; k < 2; k++) { pd->InsertNextValue(value); id->InsertNextValue(pid); pid++; xd->InsertNextValue(x + k); yd->InsertNextValue(y + j); zd->InsertNextValue(i); points->InsertNextPoint(x + k, y + j, i); } } } output->SetPoints(points); points->Delete(); id->Delete(); xd->Delete(); yd->Delete(); zd->Delete(); pd->Delete(); vtkDoubleArray* cd = vtkDoubleArray::New(); cd->SetNumberOfComponents(1); cd->SetName("Cell Value"); output->GetCellData()->AddArray(cd); id = vtkIdTypeArray::New(); id->SetNumberOfComponents(1); id->SetName("Cell Label"); output->GetCellData()->AddArray(id); output->GetCellData()->SetGlobalIds(id); xd = vtkDoubleArray::New(); xd->SetNumberOfComponents(1); xd->SetName("Cell X"); output->GetCellData()->AddArray(xd); yd = vtkDoubleArray::New(); yd->SetNumberOfComponents(1); yd->SetName("Cell Y"); output->GetCellData()->AddArray(yd); zd = vtkDoubleArray::New(); zd->SetNumberOfComponents(1); zd->SetName("Cell Z"); output->GetCellData()->AddArray(zd); output->Allocate(); vtkIdType ptcells[8]; vtkIdType cid = 0; for (int i = 0; i < 1; i++) { for (int j = 0; j < numCells; j++) { if (this->CheckAbort()) { break; } for (int k = 0; k < 1; k++) { cd->InsertNextValue(value); id->InsertNextValue(cid); cid++; xd->InsertNextValue(x + k + 0.5); // center of the cell yd->InsertNextValue(y + j + 0.5); zd->InsertNextValue(i + 0.5); ptcells[0] = (i + 0) * ((numCells + 1) * 2) + (j + 0) * 2 + (k + 0); ptcells[1] = (i + 0) * ((numCells + 1) * 2) + (j + 0) * 2 + (k + 1); ptcells[2] = (i + 0) * ((numCells + 1) * 2) + (j + 1) * 2 + (k + 0); ptcells[3] = (i + 0) * ((numCells + 1) * 2) + (j + 1) * 2 + (k + 1); ptcells[4] = (i + 1) * ((numCells + 1) * 2) + (j + 0) * 2 + (k + 0); ptcells[5] = (i + 1) * ((numCells + 1) * 2) + (j + 0) * 2 + (k + 1); ptcells[6] = (i + 1) * ((numCells + 1) * 2) + (j + 1) * 2 + (k + 0); ptcells[7] = (i + 1) * ((numCells + 1) * 2) + (j + 1) * 2 + (k + 1); output->InsertNextCell(VTK_VOXEL, 8, ptcells); } } } id->Delete(); xd->Delete(); yd->Delete(); zd->Delete(); cd->Delete(); return 1; } //------------------------------------------------------------------------------ void vtkTimeSourceExample::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Analytic: " << (this->Analytic ? "ON" : "OFF") << endl; os << indent << "XAmplitude: " << this->XAmplitude << endl; os << indent << "YAmplitude: " << this->YAmplitude << endl; os << indent << "Growing: " << this->Growing << endl; } VTK_ABI_NAMESPACE_END