From 948ac6699de8555a8aca94ccaeac3e64f15fc444 Mon Sep 17 00:00:00 2001 From: rnv Date: Wed, 26 Nov 2014 13:33:26 +0300 Subject: [PATCH] Create plugin as a filter which allows analyze difference between two time steps of one data array (field). Added the following server manager properties: 1. Property is responsible for enumeration the scalar array names of input data set; 2. Property is responsible for specifying the first time step; 3. Property is responsible for specifying the second time step; 4. Property is responsible for specifying the prefix of new array name. Filter is capable of reading various data objects. Also filter can return the corresponding errors if the input data are not correct or property of user interface controls is invalid. This filter appointed into "Temporal" group of filters. Added the icon to this filter. --- src/Plugins/CMakeLists.txt | 1 + .../DifferenceTimesteps/CMakeLists.txt | 38 ++ .../DifferenceTimesteps.xml | 124 +++++ .../DifferenceTimestepsGUI.xml | 5 + .../pqDifferenceTimesteps.qrc | 5 + .../resources/timesteps-icon.png | Bin 0 -> 25991 bytes .../vtkDifferenceTimestepsFilter.cxx | 507 ++++++++++++++++++ .../vtkDifferenceTimestepsFilter.h | 148 +++++ 8 files changed, 828 insertions(+) create mode 100644 src/Plugins/DifferenceTimesteps/CMakeLists.txt create mode 100644 src/Plugins/DifferenceTimesteps/DifferenceTimesteps.xml create mode 100644 src/Plugins/DifferenceTimesteps/DifferenceTimestepsGUI.xml create mode 100644 src/Plugins/DifferenceTimesteps/pqDifferenceTimesteps.qrc create mode 100644 src/Plugins/DifferenceTimesteps/resources/timesteps-icon.png create mode 100644 src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.cxx create mode 100644 src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.h diff --git a/src/Plugins/CMakeLists.txt b/src/Plugins/CMakeLists.txt index 52b6e529..357a7448 100755 --- a/src/Plugins/CMakeLists.txt +++ b/src/Plugins/CMakeLists.txt @@ -32,6 +32,7 @@ SET(_subdirs ElevationSurface ScaleVector EllipseBuilder + DifferenceTimesteps ) IF(NOT SALOME_LIGHT_ONLY) diff --git a/src/Plugins/DifferenceTimesteps/CMakeLists.txt b/src/Plugins/DifferenceTimesteps/CMakeLists.txt new file mode 100644 index 00000000..5208ade7 --- /dev/null +++ b/src/Plugins/DifferenceTimesteps/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2014 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# Author : Maxim Glibin + +PROJECT(DifferenceTimesteps) + +cmake_minimum_required(VERSION 2.8) + +FIND_PACKAGE(ParaView REQUIRED) +INCLUDE(${PARAVIEW_USE_FILE}) + +ADD_PARAVIEW_PLUGIN(DifferenceTimesteps "1.0" + SERVER_MANAGER_XML DifferenceTimesteps.xml + SERVER_MANAGER_SOURCES vtkDifferenceTimestepsFilter.cxx + GUI_RESOURCES pqDifferenceTimesteps.qrc + GUI_RESOURCE_FILES DifferenceTimestepsGUI.xml + ) + +INSTALL( + TARGETS DifferenceTimesteps + DESTINATION lib/paraview +) diff --git a/src/Plugins/DifferenceTimesteps/DifferenceTimesteps.xml b/src/Plugins/DifferenceTimesteps/DifferenceTimesteps.xml new file mode 100644 index 00000000..669b722b --- /dev/null +++ b/src/Plugins/DifferenceTimesteps/DifferenceTimesteps.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + This property specifies the input to DifferenceTimesteps filter. + + + + + + + + + + + + + + + + This property indicates the scalar array name to compute difference. + + + + + + + Available timestep values. + + + + + + + + + + + + + + + Define a first time step. + + + + + + + + + + + Define a second time step. + + + + + + Prefix to a new array name. + + + + + + diff --git a/src/Plugins/DifferenceTimesteps/DifferenceTimestepsGUI.xml b/src/Plugins/DifferenceTimesteps/DifferenceTimestepsGUI.xml new file mode 100644 index 00000000..e2a04550 --- /dev/null +++ b/src/Plugins/DifferenceTimesteps/DifferenceTimestepsGUI.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Plugins/DifferenceTimesteps/pqDifferenceTimesteps.qrc b/src/Plugins/DifferenceTimesteps/pqDifferenceTimesteps.qrc new file mode 100644 index 00000000..85fa5c3e --- /dev/null +++ b/src/Plugins/DifferenceTimesteps/pqDifferenceTimesteps.qrc @@ -0,0 +1,5 @@ + + + resources/timesteps-icon.png + + diff --git a/src/Plugins/DifferenceTimesteps/resources/timesteps-icon.png b/src/Plugins/DifferenceTimesteps/resources/timesteps-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..28feea5c35a3e79213c71da39ded23e45ab5e2d1 GIT binary patch literal 25991 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 literal 0 HcmV?d00001 diff --git a/src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.cxx b/src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.cxx new file mode 100644 index 00000000..7749f9c1 --- /dev/null +++ b/src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.cxx @@ -0,0 +1,507 @@ +// Copyright (C) 2014 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// Author : Maxim Glibin + +#include "vtkDifferenceTimestepsFilter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Temporal difference of data array +vtkDataArray* DataTempDiffArray(vtkDataArray* theDataArray, + vtkIdType theNumComp, + vtkIdType theNumTuple, + const char* thePrefix) +{ + // Create the new array + vtkAbstractArray *anAbstractArray = theDataArray->CreateArray(theDataArray->GetDataType()); + vtkDataArray *anOutput = vtkDataArray::SafeDownCast(anAbstractArray); + + // Initialize and appoint a new name + anOutput->SetNumberOfComponents(theNumComp); + anOutput->SetNumberOfTuples(theNumTuple); + vtkstd::string aNewName = vtkstd::string(thePrefix) + theDataArray->GetName(); + anOutput->SetName(aNewName.c_str()); + + return anOutput; +} + +// Templated difference function +template +void vtkTemporalDataDifference( + vtkDifferenceTimestepsFilter* theDTF, + vtkDataArray* theOutput, + vtkDataArray** theArrays, + vtkIdType theNumComp, + T *) +{ + T* anOutputData = static_cast(theOutput->GetVoidPointer(0)); + T* anInputData0 = static_cast(theArrays[0]->GetVoidPointer(0)); + T* anInputData1 = static_cast(theArrays[1]->GetVoidPointer(0)); + + vtkIdType N = theArrays[0]->GetNumberOfTuples(); + for (vtkIdType t = 0; t < N; ++t) + { + T* x0 = &anInputData0[t*theNumComp]; + T* x1 = &anInputData1[t*theNumComp]; + for (int c = 0; c < theNumComp; ++c) + { + // Compute the difference + *anOutputData++ = static_cast(x1[c]-x0[c]); + } + } + theOutput->SetNumberOfTuples(N); +} + +vtkStandardNewMacro(vtkDifferenceTimestepsFilter); + +//-------------------------------------------------------------------------------------------------- +vtkDifferenceTimestepsFilter::vtkDifferenceTimestepsFilter() +{ + this->NumberTimeSteps = 0; + this->RangeIndicesTimeSteps[0] = 0; + this->RangeIndicesTimeSteps[1] = 0; + this->FirstTimeStepIndex = 0.0; + this->SecondTimeStepIndex = 0.0; + this->TimeStepValues.clear(); + this->ArrayNamePrefix = NULL; + + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + + // Set the input data array that the algorithm will process + this->SetInputArrayToProcess( + 0, + 0, + 0, + vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//-------------------------------------------------------------------------------------------------- +vtkDifferenceTimestepsFilter::~vtkDifferenceTimestepsFilter() +{ + this->TimeStepValues.clear(); + this->SetArrayNamePrefix(NULL); +} + +//-------------------------------------------------------------------------------------------------- +void vtkDifferenceTimestepsFilter::PrintSelf(ostream& theOS, vtkIndent theIndent) +{ + this->Superclass::PrintSelf(theOS, theIndent); + theOS << theIndent << "Number of time steps : " << this->NumberTimeSteps << endl; + theOS << theIndent << "First time step : " << this->FirstTimeStepIndex << endl; + theOS << theIndent << "Second time step : " << this->SecondTimeStepIndex << endl; + theOS << theIndent << "Field association : " + << vtkDataObject::GetAssociationTypeAsString(this->GetInputFieldAssociation()) << endl; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::FillInputPortInformation( + int thePort, vtkInformation* theInfo) +{ + if (thePort == 0) + theInfo->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + + return 1; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::FillOutputPortInformation( + int vtkNotUsed(thePort), vtkInformation* theInfo) +{ + theInfo->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + return 1; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::RequestDataObject( + vtkInformation* vtkNotUsed(theRequest), + vtkInformationVector** theInputVector, + vtkInformationVector* theOutputVector) +{ + if (this->GetNumberOfInputPorts() == 0 || this->GetNumberOfOutputPorts() == 0) + return 1; + + vtkInformation* anInputInfo = theInputVector[0]->GetInformationObject(0); + if (anInputInfo == NULL) + { + vtkErrorMacro(<< "Input information vector is missed."); + return 0; + } + + vtkDataObject *anInputObj = anInputInfo->Get(vtkDataObject::DATA_OBJECT()); + if (anInputObj != NULL) + { + // For each output + for (int i = 0; i < this->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* anOutputInfo = theOutputVector->GetInformationObject(i); + vtkDataObject *anOutputObj = anOutputInfo->Get(vtkDataObject::DATA_OBJECT()); + if (!anOutputObj || !anOutputObj->IsA(anInputObj->GetClassName())) + { + vtkDataObject* aNewOutput = anInputObj->NewInstance(); + anOutputInfo->Set(vtkDataObject::DATA_OBJECT(), aNewOutput); + aNewOutput->Delete(); + } + } + return 1; + } + return 0; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::RequestInformation( + vtkInformation* vtkNotUsed(theRequest), + vtkInformationVector** theInputVector, + vtkInformationVector* theOutputVector) +{ + // Get input and output information objects + vtkInformation *anInInfo = theInputVector[0]->GetInformationObject(0); + vtkInformation *anOutInfo = theOutputVector->GetInformationObject(0); + + // Check for presence more than one time step + if (anInInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) + { + // Find time on input + this->NumberTimeSteps = anInInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + if (this->NumberTimeSteps < 2) + { + vtkErrorMacro(<< "Not enough numbers of time steps: " << this->NumberTimeSteps); + return 0; + } + // Get time step values + this->TimeStepValues.resize(this->NumberTimeSteps); + anInInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), &this->TimeStepValues[0]); + if (this->TimeStepValues.size() == 0) + { + vtkErrorMacro(<<"Array of time steps is empty."); + return 0; + } + } + else + { + vtkErrorMacro(<< "No time steps in input data."); + return 0; + } + + // Update range of indices of the time steps + this->RangeIndicesTimeSteps[0] = 0; + this->RangeIndicesTimeSteps[1] = this->NumberTimeSteps - 1; + + // The output data of this filter has no time associated with it. + // It is the result of computation difference between two time steps. + // Unset the time steps + if (anOutInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) + anOutInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + + // Unset the time range + if(anOutInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE())) + anOutInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE()); + + return 1; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::RequestUpdateExtent(vtkInformation* theRequest, + vtkInformationVector** theInputVector, + vtkInformationVector* theOutputVector) +{ + // Get the information objects + vtkInformation* anInputInfo = theInputVector[0]->GetInformationObject(0); + vtkInformation* anOutputInfo = theOutputVector->GetInformationObject(0); + + // Indices must not go beyond the range of indices of the time steps + if (this->FirstTimeStepIndex >= this->NumberTimeSteps || this->FirstTimeStepIndex < 0) + { + vtkErrorMacro(<< "Specified index of the first time step [" + << this->FirstTimeStepIndex + << "] is outside the range of indices."); + return 0; + } + if (this->SecondTimeStepIndex >= this->NumberTimeSteps || this->SecondTimeStepIndex < 0) + { + vtkErrorMacro(<< "Specified index of the second time step [" + << this->SecondTimeStepIndex + << "] is outside the range of indices."); + return 0; + } + + // Warn if the selected time steps are equal + if (this->FirstTimeStepIndex == this->SecondTimeStepIndex) + { + vtkWarningMacro(<< "First and second indices [" + << this->FirstTimeStepIndex + << " = " << this->SecondTimeStepIndex + << "] are the same."); + } + + // Find the required input time steps and request them + if (anOutputInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP())) + { + // Get the available input times + double *anInputTimes = anInputInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + if (anInputTimes != NULL) + { + // Compute the requested times + double anInputUpdateTimes[2]; + int aNumberInputUpdateTimes(0); + + // For each the requested time mark the required input times + anInputUpdateTimes[aNumberInputUpdateTimes++] = anInputTimes[this->FirstTimeStepIndex]; + anInputUpdateTimes[aNumberInputUpdateTimes++] = anInputTimes[this->SecondTimeStepIndex]; + + // Make the multiple time requests upstream and use set of time-stamped data + // objects are stored in time order in a vtkMultiBlockDataSet object + anInputInfo->Set(vtkMultiTimeStepAlgorithm::UPDATE_TIME_STEPS(), + anInputUpdateTimes, aNumberInputUpdateTimes); + } + } + return 1; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::RequestData(vtkInformation* vtkNotUsed(theRequest), + vtkInformationVector** theInputVector, + vtkInformationVector* theOutputVector) +{ + // Get the information objects + vtkInformation *anInputInfo = theInputVector[0]->GetInformationObject(0); + vtkInformation *anOutputInfo = theOutputVector->GetInformationObject(0); + + vtkDataObject *anOutputDataObj = NULL; + + vtkMultiBlockDataSet *anInputData = + vtkMultiBlockDataSet::SafeDownCast(anInputInfo->Get(vtkDataObject::DATA_OBJECT())); + + int aNumberTimeSteps = anInputData->GetNumberOfBlocks(); + if (aNumberTimeSteps == 2) + { + // Get data objects + vtkDataObject* aData0 = anInputData->GetBlock(0); + vtkDataObject* aData1 = anInputData->GetBlock(1); + if (aData0 == NULL && aData1 == NULL) + { + vtkErrorMacro(<< "Null data set."); + return 0; + } + + // Compute difference between two objects + anOutputDataObj = this->DifferenceDataObject(aData0, aData1); + anOutputInfo->Set(vtkDataObject::DATA_OBJECT(), anOutputDataObj); + if (anOutputDataObj != NULL) + anOutputDataObj->Delete(); + } + else + { + vtkErrorMacro(<< "The amount of time blocks is not correct: " << aNumberTimeSteps); + return 0; + } + + return 1; +} + +//-------------------------------------------------------------------------------------------------- +vtkDataObject* vtkDifferenceTimestepsFilter::DifferenceDataObject(vtkDataObject* theInput1, + vtkDataObject* theInput2) +{ + // Determine the input object type + if (theInput1->IsA("vtkDataSet")) + { + vtkDataSet *anInDataSet1 = vtkDataSet::SafeDownCast(theInput1); + vtkDataSet *anInDataSet2 = vtkDataSet::SafeDownCast(theInput2); + return this->DifferenceDataSet(anInDataSet1, anInDataSet2); + } + else if (theInput1->IsA("vtkCompositeDataSet")) + { + // It is essential that aMGDataSet[0] an aMGDataSet[1] has the same structure. + vtkCompositeDataSet* aMGDataSet[2]; + aMGDataSet[0] = vtkCompositeDataSet::SafeDownCast(theInput1); + aMGDataSet[1] = vtkCompositeDataSet::SafeDownCast(theInput2); + + vtkCompositeDataSet *anOutput = aMGDataSet[0]->NewInstance(); + anOutput->CopyStructure(aMGDataSet[0]); + + vtkSmartPointer anIter; + anIter.TakeReference(aMGDataSet[0]->NewIterator()); + for (anIter->InitTraversal(); !anIter->IsDoneWithTraversal(); anIter->GoToNextItem()) + { + vtkDataObject* aDataObj1 = anIter->GetCurrentDataObject(); + vtkDataObject* aDataObj2 = aMGDataSet[1]->GetDataSet(anIter); + if (aDataObj1 == NULL || aDataObj2 == NULL) + { + vtkWarningMacro("The composite datasets were not identical in structure."); + continue; + } + + vtkDataObject *aResultDObj = this->DifferenceDataObject(aDataObj1, aDataObj2); + if (aResultDObj != NULL) + { + anOutput->SetDataSet(anIter, aResultDObj); + aResultDObj->Delete(); + } + else + { + vtkErrorMacro(<< "Unexpected error during computation of the difference."); + return NULL; + } + } + return anOutput; + } + else + { + vtkErrorMacro("We cannot yet compute difference of this type of dataset."); + return NULL; + } +} + +//-------------------------------------------------------------------------------------------------- +vtkDataSet* vtkDifferenceTimestepsFilter::DifferenceDataSet(vtkDataSet* theInput1, + vtkDataSet* theInput2) +{ + vtkDataSet *anInput[2]; + anInput[0] = theInput1; + anInput[1] = theInput2; + + // Copy input structure into output + vtkDataSet *anOutput = anInput[0]->NewInstance(); + anOutput->CopyStructure(anInput[0]); + + vtkstd::vector anArrays; + vtkDataArray *anOutputArray; + + // Compute the difference of the the specified point or cell data array + vtkDataArray* aDataArray0 = this->GetInputArrayToProcess(0, anInput[0]); + vtkDataArray* aDataArray1 = this->GetInputArrayToProcess(0, anInput[1]); + if (aDataArray0 == NULL || aDataArray1 == NULL) + { + vtkErrorMacro(<< "Input array to process is empty."); + return NULL; + } + anArrays.push_back(aDataArray0); + anArrays.push_back(aDataArray1); + + if (anArrays.size() > 1) + { + if (!this->VerifyArrays(&anArrays[0], 2)) + { + vtkErrorMacro(<< "Verification of data arrays has failed."); + return NULL; + } + + anOutputArray = this->DifferenceDataArray(&anArrays[0], anArrays[0]->GetNumberOfTuples()); + // Determine a field association + if (this->GetInputFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS) + { + // For point data + anOutput->GetPointData()->AddArray(anOutputArray); + } + else if (this->GetInputFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_CELLS) + { + // For cell data + anOutput->GetCellData()->AddArray(anOutputArray); + } + else + { + vtkErrorMacro(<< "Solution is not implemeted yet."); + return NULL; + } + anOutputArray->Delete(); + anArrays.clear(); + } + + return anOutput; +} + +//-------------------------------------------------------------------------------------------------- +vtkDataArray* vtkDifferenceTimestepsFilter::DifferenceDataArray(vtkDataArray** theArrays, + vtkIdType theNumTuple) +{ + // Create the output array based on the number of tuple and components + // with a new name containing the specified prefix + int aNumComp = theArrays[0]->GetNumberOfComponents(); + vtkDataArray *anOutput = + DataTempDiffArray(theArrays[0], aNumComp, theNumTuple, this->ArrayNamePrefix); + + // Now do the computation of the difference + switch (theArrays[0]->GetDataType()) + { + vtkTemplateMacro( + vtkTemporalDataDifference(this, anOutput, theArrays, aNumComp, static_cast(0))); + default: + vtkErrorMacro(<< "Execute: unknown scalar type."); + return NULL; + } + + return anOutput; +} + +//-------------------------------------------------------------------------------------------------- +int vtkDifferenceTimestepsFilter::GetInputFieldAssociation() +{ + vtkInformationVector *anInputArrayVec = this->GetInformation()->Get(INPUT_ARRAYS_TO_PROCESS()); + vtkInformation *anInputArrayInfo = anInputArrayVec->GetInformationObject(0); + return anInputArrayInfo->Get(vtkDataObject::FIELD_ASSOCIATION()); +} + +//-------------------------------------------------------------------------------------------------- +bool vtkDifferenceTimestepsFilter::VerifyArrays(vtkDataArray **theArrays, int theNumArrays) +{ + // Get all required data to compare with other + const char* anArrayName = theArrays[0]->GetName(); + vtkIdType aNumTuples = theArrays[0]->GetNumberOfTuples(); + vtkIdType aNumComponents = theArrays[0]->GetNumberOfComponents(); + + for (int i = 1; i < theNumArrays; ++i) + { + if (strcmp(theArrays[i]->GetName(), anArrayName) != 0) + { + vtkWarningMacro(<< "Computation of difference aborted for dataset because " + << "the array name in each time step are different.") + return false; + } + + if (theArrays[i]->GetNumberOfTuples() != aNumTuples) + { + vtkWarningMacro(<< "Computation of difference aborted for dataset because " + << "the number of tuples in each time step are different.") + return false; + } + + if (theArrays[i]->GetNumberOfComponents() != aNumComponents) + { + vtkWarningMacro(<< "Computation of difference aborted for dataset because " + << "the number of components in each time step are different.") + return false; + } + } + + return true; +} diff --git a/src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.h b/src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.h new file mode 100644 index 00000000..12bbf63c --- /dev/null +++ b/src/Plugins/DifferenceTimesteps/vtkDifferenceTimestepsFilter.h @@ -0,0 +1,148 @@ +// Copyright (C) 2014 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// Author : Maxim Glibin + +#ifndef __DifferenceTimestepsFilter_h_ +#define __DifferenceTimestepsFilter_h_ + +#include + +#include + +class vtkDataSet; +class vtkStringArray; + +/** + * Description of class: + * Class allows to compute difference between two time steps of one data array (field). +*/ +class VTK_EXPORT vtkDifferenceTimestepsFilter : public vtkMultiTimeStepAlgorithm +{ +public: + /// Returns pointer on a new instance of the class + static vtkDifferenceTimestepsFilter* New(); + + vtkTypeMacro(vtkDifferenceTimestepsFilter, vtkMultiTimeStepAlgorithm); + + /// Prints current state of the objects + virtual void PrintSelf(ostream &, vtkIndent); + + // Description: + // Set/Get methods for first time step. + vtkSetMacro(FirstTimeStepIndex, int); + vtkGetMacro(FirstTimeStepIndex, int); + + // Description: + // Set/Get methods for first time step. + vtkSetMacro(SecondTimeStepIndex, int); + vtkGetMacro(SecondTimeStepIndex, int); + + // Description: + // Get methods for range of indices of time steps. + vtkGetVector2Macro(RangeIndicesTimeSteps, int); + + // Description: + // Set/Get methods for prefix of array name. + vtkSetStringMacro(ArrayNamePrefix); + vtkGetStringMacro(ArrayNamePrefix); + +protected: + /// Constructor & destructor + vtkDifferenceTimestepsFilter(); + virtual ~vtkDifferenceTimestepsFilter(); + + /// The methods which is called on filtering data + virtual int FillInputPortInformation(int, vtkInformation *); + + virtual int FillOutputPortInformation(int, vtkInformation *); + + virtual int RequestDataObject(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestInformation(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestUpdateExtent(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + // Description: + // General computation differences routine for any type on input data. This + // is called recursively when heirarchical/multiblock data is encountered. + vtkDataObject *DifferenceDataObject(vtkDataObject* theInput1, + vtkDataObject* theInput2); + + // Description: + // Root level interpolation for a concrete dataset object. + // Point/Cell data and points are different. + // Needs improving if connectivity is to be handled. + virtual vtkDataSet *DifferenceDataSet(vtkDataSet* theInput1, + vtkDataSet* theInput2); + + // Description: + // Compute difference a single vtkDataArray. Called from computation + // of the difference routine on pointdata or celldata. + virtual vtkDataArray *DifferenceDataArray(vtkDataArray** theArrays, + vtkIdType theN); + + // Description: + // Range of indices of the time steps. + int RangeIndicesTimeSteps[2]; + + // Description: + // First time step index. + int FirstTimeStepIndex; + + // Description: + // Second time step index. + int SecondTimeStepIndex; + + // Description: + // Length of time steps array + int NumberTimeSteps; + + // Description: + // Array of time step values. + vtkstd::vector TimeStepValues; + + // Description: + // Prefix of array name. + char *ArrayNamePrefix; + +private: + vtkDifferenceTimestepsFilter(const vtkDifferenceTimestepsFilter &); // Not implemented yet + void operator=(const vtkDifferenceTimestepsFilter &); // Not implemented yet + + // Description: + // Get field association type. + int GetInputFieldAssociation(); + + // Description: + // Called just before computation of the difference of the dataset to ensure that + // each data array has the same array name, number of tuples or components and etc. + bool VerifyArrays(vtkDataArray **theArrays, int theNumArrays); +}; + +#endif // __DifferenceTimestepsFilter_h_ -- 2.39.2