Salome HOME
The last memory leak hunting. All tests do not leak.
[modules/paravis.git] / src / Plugins / EllipseBuilder / vtkEllipseBuilderFilter.cxx
1 // Copyright (C) 2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18
19 #include "vtkEllipseBuilderFilter.h"
20
21 #include <vtkObjectFactory.h>
22 #include <vtkInformation.h>
23 #include <vtkInformationVector.h>
24 #include <vtkMultiBlockDataSet.h>
25 #include <vtkDataObjectTreeIterator.h>
26 #include <vtkDataSet.h>
27 #include <vtkPoints.h>
28 #include <vtkPointData.h>
29 #include <vtkDataArray.h>
30 #include <vtkStringArray.h>
31 #include <vtkUnstructuredGrid.h>
32 #include <vtkPolyVertex.h>
33 #include <vtkMath.h>
34
35 #include <complex>
36 #include <algorithm>
37 #include <vector>
38 #include <cmath>
39
40 using namespace std;
41
42 //------------------------------------------------------------------------------
43 bool isStringInList(const list<string>& aList, const string& theName)
44 {
45   list<string>::const_iterator anIter;
46   for (anIter = aList.begin(); anIter != aList.end(); anIter++)
47     {
48       // Compares the values of the string.
49       if ( (*anIter).compare(theName) == 0)
50         return true;
51     }
52   return false;
53 }
54
55 //------------------------------------------------------------------------------
56 void add2List(const list<string>& theSource, list<string>& theDestination)
57 {
58   list<string>::const_iterator anIter;
59   for (anIter = theSource.begin(); anIter != theSource.end(); anIter++)
60     {
61       // Add the item to the list if it does not exist
62       if (!isStringInList(theDestination, *anIter))
63         theDestination.push_back(*anIter);
64     }
65 }
66
67 //------------------------------------------------------------------------------
68 double maximumElement(vector< complex<double> >& theList)
69 {
70   double aMaximum;
71   vector<double> tmpList;
72   vector< complex<double> >::iterator it;
73   for (it = theList.begin(); it != theList.end(); ++it)
74     {
75       tmpList.push_back(((*it)*conj(*it)).real());
76     }
77   aMaximum = *max_element(tmpList.begin(), tmpList.end());
78   return aMaximum;
79 }
80
81 //------------------------------------------------------------------------------
82 list<std::string> GetListOfFields(vtkDataObject* theObject)
83 {
84   list<string> aList;
85   
86   if (theObject->IsA("vtkDataSet"))
87     {
88       vtkDataSet* aDataSet = vtkDataSet::SafeDownCast(theObject);
89       vtkPointData* aPntData = aDataSet->GetPointData();
90       
91       // Add fields name on points
92       int aNbArrays = aPntData->GetNumberOfArrays();
93       for (int i = 0; i<aNbArrays; i++)
94         {
95           if( vtkDataArray* anArray = aPntData->GetArray(i) ) {
96             //Data array should contains at least 3 components (1 - DX, 2 - DY, 3 - DZ)
97             if( anArray->GetNumberOfComponents() >= 3 ) {
98               const char* aName = aPntData->GetArrayName(i);
99               aList.push_back(aName);
100             }
101           }
102         }
103     }
104   return aList;
105 }
106
107 //------------------------------------------------------------------------------
108 vtkStandardNewMacro(vtkEllipseBuilderFilter);
109
110 //------------------------------------------------------------------------------
111 vtkEllipseBuilderFilter::vtkEllipseBuilderFilter() : vtkMultiBlockDataSetAlgorithm()
112 {
113   this->RealField = NULL;
114   this->ImagField = NULL;
115   this->FieldList = vtkStringArray::New();
116 }
117
118 //------------------------------------------------------------------------------
119 vtkEllipseBuilderFilter::~vtkEllipseBuilderFilter()
120 {
121   this->SetRealField(NULL);
122   this->SetRealField(NULL);
123   this->FieldList->Delete();
124 }
125
126 //------------------------------------------------------------------------------
127 int vtkEllipseBuilderFilter::RequestData(vtkInformation* vtkNotUsed(request),
128                                          vtkInformationVector** theInputVector,
129                                          vtkInformationVector* theOutputVector)
130 {
131   int aResolution = this->Resolution;
132   if(aResolution <=0 )
133     return 0;
134   if( this->ScaleFactor == 0.0 )
135     return 0;
136
137   int anAxis = this->Axis;
138   
139   // Get the info objects
140   vtkMultiBlockDataSet* anInputMDSet = vtkMultiBlockDataSet::GetData(theInputVector[0], 0);
141   vtkMultiBlockDataSet* anOutputMDSet = vtkMultiBlockDataSet::GetData(theOutputVector, 0);
142   
143   double a, b, z_point;
144   vector< complex<double> > circle;
145
146   // Points Ellipses
147   double range, min, max, delta;
148   if(this->EndAngle > this->StartAngle) {
149     min = this->StartAngle;
150     max = this->EndAngle;
151   } else {
152     min = this->StartAngle;
153     max = this->EndAngle + 360.;
154   }
155   range = max-min;
156   delta = range/(double)aResolution;
157   for (double iter = min;  iter < max; iter+=delta)
158     {
159       a = cos(vtkMath::RadiansFromDegrees(iter));
160       b = sin(vtkMath::RadiansFromDegrees(iter));
161       complex<double> aVal(a, b);
162       circle.push_back(aVal);
163     }
164   
165   //Scale Factor    
166   double aScaleFactor;
167   aScaleFactor = 1./this->ScaleFactor;  
168     
169   vtkDataObjectTreeIterator* anIter = anInputMDSet->NewTreeIterator();
170   anIter->VisitOnlyLeavesOff();
171   bool created = false;
172   for (anIter->InitTraversal(); !anIter->IsDoneWithTraversal(); anIter->GoToNextItem())
173     {
174       vtkDataObject* anInputNode = anInputMDSet->GetDataSet(anIter);
175       if (anInputNode->IsA("vtkDataSet"))
176         {
177           vtkUnstructuredGrid* aSourceDS = vtkUnstructuredGrid::SafeDownCast(anInputNode);
178           if(!aSourceDS) continue;
179           
180           vtkPointData* aPointData = aSourceDS->GetPointData();
181           if(!aPointData) continue;
182           
183           int aNumberPoints = aSourceDS->GetNumberOfPoints();
184           
185           vtkDataArray* aRealArray = vtkDataArray::SafeDownCast(aPointData->GetArray(this->RealField));
186           vtkDataArray* anImagArray = vtkDataArray::SafeDownCast(aPointData->GetArray(this->ImagField));
187           
188           if(!aRealArray || !anImagArray) continue;
189           
190           int aNumberOfRealComponents = aRealArray->GetNumberOfComponents();
191           int aNumberOfImagComponents = anImagArray->GetNumberOfComponents();              
192           if (aNumberOfRealComponents >= 3 and aNumberOfImagComponents >= 3)
193             {
194               anOutputMDSet->CopyStructure(anInputMDSet);
195               vtkUnstructuredGrid* aCloneDS = aSourceDS->NewInstance();
196               vtkPoints* aClonePoints = vtkPoints::New();
197               aCloneDS->SetPoints(aClonePoints);
198               aClonePoints->Delete();
199               anOutputMDSet->SetDataSet(anIter, aCloneDS);
200               aCloneDS->Delete();             
201               double rx, ry, ix, iy;
202               created = true;
203               for (int j = 0; j < aNumberPoints; j++)
204                 {
205                   z_point = aSourceDS->GetPoint(j)[2];
206                   
207                   if (anAxis == 2)      // Z : DX and DY
208                     {
209                       rx = aRealArray->GetTuple(j)[0];
210                       ry = aRealArray->GetTuple(j)[1];
211                       ix = anImagArray->GetTuple(j)[0];
212                       iy = anImagArray->GetTuple(j)[1];
213                     }
214                   else if (anAxis == 1) // Y : DX and DZ
215                     {
216                       rx = aRealArray->GetTuple(j)[0];
217                       ry = aRealArray->GetTuple(j)[2];
218                       ix = anImagArray->GetTuple(j)[0];
219                       iy = anImagArray->GetTuple(j)[2];
220                     }
221                   else                  // X : DY and DZ
222                     {
223                       rx = aRealArray->GetTuple(j)[1];
224                       ry = aRealArray->GetTuple(j)[2];
225                       ix = anImagArray->GetTuple(j)[1];
226                       iy = anImagArray->GetTuple(j)[2];
227                     }
228                   
229                   complex<double> x(rx, ix);
230                   complex<double> y(ry, iy);               
231                   
232                   x = x / aScaleFactor;
233                   y = y / aScaleFactor;             
234
235                   double x_point, y_point;
236                   for (int r = 0; r < circle.size(); r++)
237                     {
238                       x_point = (x*circle[r]).real();
239                       y_point = (y*circle[r]).real();
240                       vtkIdType anId[1];
241                       if (anAxis == 2)
242                         anId[0] = aClonePoints->InsertNextPoint(x_point, y_point, z_point);
243                       else if (anAxis == 1)
244                         anId[0] = aClonePoints->InsertNextPoint(x_point, z_point, y_point);
245                       else
246                         anId[0] = aClonePoints->InsertNextPoint(z_point, x_point, y_point);                   
247                       aCloneDS->InsertNextCell(VTK_VERTEX, 1, anId);
248                     }             
249                 }
250             }
251           else
252             {
253               continue;
254             }
255         }
256     }
257   anIter->Delete();
258   if(!created)
259     return 0;
260   return 1;
261 }
262
263 //------------------------------------------------------------------------------
264 int vtkEllipseBuilderFilter::RequestInformation(vtkInformation* request,
265                                                 vtkInformationVector **theInputVector,
266                                                 vtkInformationVector *theOutputVector)
267 {
268     // Retrieve an instance of vtkMultiBlockDataSet class from an information object.
269     vtkMultiBlockDataSet* anInputMDataSet = vtkMultiBlockDataSet::GetData(theInputVector[0], 0);
270
271     list<string> aList;
272     vtkDataObjectTreeIterator* anIter = anInputMDataSet->NewTreeIterator();
273     anIter->VisitOnlyLeavesOff();
274     for (anIter->InitTraversal(); !anIter->IsDoneWithTraversal(); anIter->GoToNextItem())
275     {
276         vtkDataObject* anInputNode = anInputMDataSet->GetDataSet(anIter);
277         if (anInputNode->IsA("vtkDataSet"))
278         {
279           list<string> aSubList = GetListOfFields(anInputNode);
280           add2List(aSubList, aList);
281         }
282     }
283     anIter->Delete();
284     
285     this->FieldList->Reset();
286     this->FieldList->SetNumberOfValues(aList.size());
287     list<string>::const_iterator anIterName;
288     int i = 0;
289     for (anIterName = aList.begin(); anIterName != aList.end(); anIterName++)
290     {
291         this->FieldList->SetValue(i, *anIterName);
292         i++;
293     }
294     
295     return this->Superclass::RequestInformation(request, theInputVector, theOutputVector);
296 }
297
298
299 //------------------------------------------------------------------------------
300 vtkStringArray* vtkEllipseBuilderFilter::GetFieldList()
301 {
302     return this->FieldList;
303 }
304
305 //------------------------------------------------------------------------------
306 void vtkEllipseBuilderFilter::PrintSelf(ostream& os, vtkIndent indent)
307 {
308     this->Superclass::PrintSelf(os, indent);
309     os << indent << "Real Field : " << this->RealField << endl;
310     os << indent << "Imag Field : " << this->ImagField << endl;
311     os << indent << "Start Angle : " << this->StartAngle << endl;
312     os << indent << "End Angle : " << this->EndAngle << endl;
313     os << indent << "Scale Factor : " << this->ScaleFactor << endl;
314     os << indent << "Scale Resolution : " << this->Resolution << endl;
315     os << indent << "Axis : " << this->Axis << endl;
316 }
317