1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkWeightedTransformFilter.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkWeightedTransformFilter.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkFieldData.h"
19 #include "vtkFloatArray.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkLinearTransform.h"
23 #include "vtkMath.h"
24 #include "vtkMatrix4x4.h"
25 #include "vtkObjectFactory.h"
26 #include "vtkPointData.h"
27 #include "vtkPointSet.h"
28 #include "vtkUnsignedShortArray.h"
29 
30 #include <vector>
31 
32 vtkStandardNewMacro(vtkWeightedTransformFilter);
33 
34 // helper functions.  Can't easily get to these in Matrix4x4 as written.
35 
LinearTransformVector(double matrix[4][4],double in[3],double out[3])36 static inline void LinearTransformVector(double matrix[4][4], double in[3], double out[3])
37 {
38   out[0] = matrix[0][0] * in[0] + matrix[0][1] * in[1] + matrix[0][2] * in[2];
39   out[1] = matrix[1][0] * in[0] + matrix[1][1] * in[1] + matrix[1][2] * in[2];
40   out[2] = matrix[2][0] * in[0] + matrix[2][1] * in[1] + matrix[2][2] * in[2];
41 }
42 
LinearTransformPoint(double mtx[4][4],double in[3],double out[3])43 static inline void LinearTransformPoint(double mtx[4][4], double in[3], double out[3])
44 {
45   out[0] = mtx[0][0] * in[0] + mtx[0][1] * in[1] + mtx[0][2] * in[2] + mtx[0][3];
46   out[1] = mtx[1][0] * in[0] + mtx[1][1] * in[1] + mtx[1][2] * in[2] + mtx[1][3];
47   out[2] = mtx[2][0] * in[0] + mtx[2][1] * in[1] + mtx[2][2] * in[2] + mtx[2][3];
48 }
49 
50 //------------------------------------------------------------------------------
vtkWeightedTransformFilter()51 vtkWeightedTransformFilter::vtkWeightedTransformFilter()
52 {
53   this->AddInputValues = 0;
54   this->Transforms = nullptr;
55   this->NumberOfTransforms = 0;
56 
57   this->CellDataWeightArray = nullptr;
58   this->WeightArray = nullptr;
59   this->CellDataTransformIndexArray = nullptr;
60   this->TransformIndexArray = nullptr;
61 }
62 
63 //------------------------------------------------------------------------------
~vtkWeightedTransformFilter()64 vtkWeightedTransformFilter::~vtkWeightedTransformFilter()
65 {
66   int i;
67 
68   if (this->Transforms != nullptr)
69   {
70     for (i = 0; i < this->NumberOfTransforms; i++)
71     {
72       if (this->Transforms[i] != nullptr)
73       {
74         this->Transforms[i]->UnRegister(this);
75       }
76     }
77     delete[] this->Transforms;
78   }
79 
80   // Setting these strings to nullptr has the side-effect of deleting them.
81   this->SetCellDataWeightArray(nullptr);
82   this->SetWeightArray(nullptr);
83   this->SetCellDataTransformIndexArray(nullptr);
84   this->SetTransformIndexArray(nullptr);
85 }
86 
87 //------------------------------------------------------------------------------
SetNumberOfTransforms(int num)88 void vtkWeightedTransformFilter::SetNumberOfTransforms(int num)
89 {
90   int i;
91   vtkAbstractTransform** newTransforms;
92 
93   if (num < 0)
94   {
95     vtkErrorMacro(<< "Cannot set transform count below zero");
96     return;
97   }
98 
99   if (this->Transforms == nullptr)
100   {
101     // first time
102     this->Transforms = new vtkAbstractTransform*[num];
103     for (i = 0; i < num; i++)
104     {
105       this->Transforms[i] = nullptr;
106     }
107     this->NumberOfTransforms = num;
108     return;
109   }
110 
111   if (num == this->NumberOfTransforms)
112   {
113     return;
114   }
115 
116   if (num < this->NumberOfTransforms)
117   {
118     // create a smaller array, free up references to cut-off elements,
119     // and copy other elements
120     for (i = num; i < this->NumberOfTransforms; i++)
121     {
122       if (this->Transforms[i] != nullptr)
123       {
124         this->Transforms[i]->UnRegister(this);
125         this->Transforms[i] = nullptr;
126       }
127     }
128     newTransforms = new vtkAbstractTransform*[num];
129     for (i = 0; i < num; i++)
130     {
131       newTransforms[i] = this->Transforms[i];
132     }
133     delete[] this->Transforms;
134     this->Transforms = newTransforms;
135   }
136   else
137   {
138     // create a new array and copy elements, no unregistering needed.
139     newTransforms = new vtkAbstractTransform*[num];
140     for (i = 0; i < this->NumberOfTransforms; i++)
141     {
142       newTransforms[i] = this->Transforms[i];
143     }
144 
145     for (i = this->NumberOfTransforms; i < num; i++)
146     {
147       newTransforms[i] = nullptr;
148     }
149     delete[] this->Transforms;
150     this->Transforms = newTransforms;
151   }
152 
153   this->NumberOfTransforms = num;
154   this->Modified();
155 }
156 
157 //------------------------------------------------------------------------------
SetTransform(vtkAbstractTransform * trans,int num)158 void vtkWeightedTransformFilter::SetTransform(vtkAbstractTransform* trans, int num)
159 {
160   if (num < 0)
161   {
162     vtkErrorMacro(<< "Transform number must be greater than 0");
163     return;
164   }
165 
166   if (num >= this->NumberOfTransforms)
167   {
168     vtkErrorMacro(<< "Transform number exceeds maximum of " << this->NumberOfTransforms);
169     return;
170   }
171   if (this->Transforms[num] != nullptr)
172   {
173     this->Transforms[num]->UnRegister(this);
174   }
175   this->Transforms[num] = trans;
176   if (trans != nullptr)
177   {
178     trans->Register(this);
179   }
180   this->Modified();
181 }
182 
183 //------------------------------------------------------------------------------
GetTransform(int num)184 vtkAbstractTransform* vtkWeightedTransformFilter::GetTransform(int num)
185 {
186   if (num < 0)
187   {
188     vtkErrorMacro(<< "Transform number must be greater than 0");
189     return nullptr;
190   }
191 
192   if (num >= this->NumberOfTransforms)
193   {
194     vtkErrorMacro(<< "Transform number exceeds maximum of " << this->NumberOfTransforms);
195     return nullptr;
196   }
197 
198   return this->Transforms[num];
199 }
200 
201 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)202 int vtkWeightedTransformFilter::RequestData(vtkInformation* vtkNotUsed(request),
203   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
204 {
205   // get the info objects
206   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
207   vtkInformation* outInfo = outputVector->GetInformationObject(0);
208 
209   // get the input and output
210   vtkPointSet* input = vtkPointSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
211   vtkPointSet* output = vtkPointSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
212 
213   vtkPoints* inPts;
214   vtkPoints* newPts;
215   vtkDataArray *inVectors, *inCellVectors;
216   vtkDataArray *inNormals, *inCellNormals;
217   vtkFloatArray *newVectors = nullptr, *newCellVectors = nullptr;
218   vtkFloatArray *newNormals = nullptr, *newCellNormals = nullptr;
219   vtkIdType numPts, numCells, p;
220   int activeTransforms, allLinear;
221   int i, c, tidx;
222   int pdComponents, cdComponents;
223   double inVec[3], inPt[3], inNorm[3];
224   double xformNorm[3], cumNorm[3];
225   double xformPt[3], cumPt[3];
226   double xformVec[3], cumVec[3];
227   double derivMatrix[3][3];
228   float* weights = nullptr;
229   unsigned short* transformIndices = nullptr;
230   double thisWeight;
231   vtkDataArray *pdArray, *cdArray;
232   vtkUnsignedShortArray *tiArray, *cdtiArray;
233   vtkFieldData* fd;
234   vtkPointData *pd = input->GetPointData(), *outPD = output->GetPointData();
235   vtkCellData *cd = input->GetCellData(), *outCD = output->GetCellData();
236   vtkLinearTransform* linearTransform;
237 
238   vtkDebugMacro(<< "Executing weighted transform filter");
239 
240   // First, copy the input to the output as a starting point
241   output->CopyStructure(input);
242 
243   // Check input
244   //
245   if (this->Transforms == nullptr || this->NumberOfTransforms == 0)
246   {
247     vtkErrorMacro(<< "No transform defined!");
248     return 1;
249   }
250 
251   activeTransforms = 0;
252   for (c = 0; c < this->NumberOfTransforms; c++)
253   {
254     if (this->Transforms[c] != nullptr)
255     {
256       activeTransforms++;
257     }
258   }
259 
260   if (activeTransforms == 0)
261   {
262     vtkErrorMacro(<< "No transform defined!");
263     return 1;
264   }
265 
266   std::vector<double*> linearPtMtx(this->NumberOfTransforms, nullptr);      // non-owning ptr
267   std::vector<std::vector<double>> linearNormMtx(this->NumberOfTransforms); // owns data
268   allLinear = 1;
269   for (c = 0; c < this->NumberOfTransforms; c++)
270   {
271     if (this->Transforms[c] == nullptr)
272     {
273       continue;
274     }
275 
276     this->Transforms[c]->Update();
277 
278     if (!this->Transforms[c]->IsA("vtkLinearTransform"))
279     {
280       allLinear = 0;
281       continue;
282     }
283     linearTransform = vtkLinearTransform::SafeDownCast(this->Transforms[c]);
284     linearPtMtx[c] = linearTransform->GetMatrix()->GetData();
285     linearNormMtx[c].resize(16);
286     vtkMatrix4x4::DeepCopy(linearNormMtx[c].data(), linearTransform->GetMatrix());
287     vtkMatrix4x4::Invert(linearNormMtx[c].data(), linearNormMtx[c].data());
288     vtkMatrix4x4::Transpose(linearNormMtx[c].data(), linearNormMtx[c].data());
289   }
290 
291   pdArray = nullptr;
292   pdComponents = 0;
293   if (this->WeightArray != nullptr && this->WeightArray[0] != '\0')
294   {
295     fd = pd;
296     if (fd != nullptr)
297     {
298       pdArray = fd->GetArray(this->WeightArray);
299     }
300     if (pdArray == nullptr)
301     {
302       fd = input->GetFieldData();
303       if (fd != nullptr)
304       {
305         pdArray = fd->GetArray(this->WeightArray);
306       }
307     }
308     if (pdArray == nullptr)
309     {
310       vtkErrorMacro(<< "WeightArray " << this->WeightArray << " "
311                     << "doesn't exist");
312       return 1;
313     }
314 
315     pdComponents = pdArray->GetNumberOfComponents();
316     if (pdComponents > this->NumberOfTransforms)
317     {
318       pdComponents = this->NumberOfTransforms;
319     }
320   }
321 
322   tiArray = nullptr;
323   if (this->TransformIndexArray != nullptr && this->TransformIndexArray[0] != '\0')
324   {
325     fd = pd;
326     if (fd != nullptr)
327     {
328       tiArray = reinterpret_cast<vtkUnsignedShortArray*>(fd->GetArray(this->TransformIndexArray));
329     }
330     if (tiArray == nullptr)
331     {
332       fd = input->GetFieldData();
333       if (fd != nullptr)
334       {
335         tiArray = reinterpret_cast<vtkUnsignedShortArray*>(fd->GetArray(this->TransformIndexArray));
336       }
337     }
338     if (tiArray == nullptr)
339     {
340       vtkErrorMacro(<< "TransformIndexArray " << this->TransformIndexArray << " "
341                     << "doesn't exist");
342       return 1;
343     }
344 
345     if (pdComponents != tiArray->GetNumberOfComponents())
346     {
347       vtkWarningMacro(<< "TransformIndexArray " << this->TransformIndexArray << " "
348                       << "does not have the same number of components as WeightArray "
349                       << this->WeightArray);
350       tiArray = nullptr;
351     }
352     if (tiArray->GetDataType() != VTK_UNSIGNED_SHORT)
353     {
354       vtkWarningMacro(<< "TransformIndexArray " << this->TransformIndexArray << " "
355                       << " is not of type unsigned short, ignoring.");
356       tiArray = nullptr;
357     }
358   }
359 
360   cdArray = nullptr;
361   cdComponents = 0;
362   if (this->CellDataWeightArray != nullptr && this->CellDataWeightArray[0] != '\0')
363   {
364     fd = cd;
365     if (fd != nullptr)
366     {
367       cdArray = fd->GetArray(this->CellDataWeightArray);
368     }
369     if (cdArray == nullptr)
370     {
371       fd = input->GetFieldData();
372       if (fd != nullptr)
373       {
374         cdArray = fd->GetArray(this->CellDataWeightArray);
375       }
376     }
377     if (cdArray == nullptr)
378     {
379       vtkErrorMacro(<< "CellDataWeightArray " << this->CellDataWeightArray << " "
380                     << "doesn't exist");
381       return 1;
382     }
383     cdComponents = cdArray->GetNumberOfComponents();
384     if (cdComponents > this->NumberOfTransforms)
385     {
386       cdComponents = this->NumberOfTransforms;
387     }
388   }
389 
390   cdtiArray = nullptr;
391   if (this->CellDataTransformIndexArray != nullptr && this->CellDataTransformIndexArray[0] != '\0')
392   {
393     fd = pd;
394     if (fd != nullptr)
395     {
396       cdtiArray =
397         reinterpret_cast<vtkUnsignedShortArray*>(fd->GetArray(this->CellDataTransformIndexArray));
398     }
399     if (cdtiArray == nullptr)
400     {
401       fd = input->GetFieldData();
402       if (fd != nullptr)
403       {
404         cdtiArray =
405           reinterpret_cast<vtkUnsignedShortArray*>(fd->GetArray(this->CellDataTransformIndexArray));
406       }
407     }
408     if (cdtiArray == nullptr)
409     {
410       vtkErrorMacro(<< "CellDataTransformIndexArray " << this->CellDataTransformIndexArray << " "
411                     << "doesn't exist");
412       return 1;
413     }
414 
415     if (cdComponents != cdtiArray->GetNumberOfComponents())
416     {
417       vtkWarningMacro(<< "CellDataTransformIndexArray " << this->CellDataTransformIndexArray << " "
418                       << "does not have the same number of components as "
419                       << "CellDataWeightArray " << this->WeightArray);
420       cdtiArray = nullptr;
421     }
422     if (cdtiArray && (cdtiArray->GetDataType() != VTK_UNSIGNED_SHORT))
423     {
424       vtkWarningMacro(<< "CellDataTransformIndexArray " << this->CellDataTransformIndexArray << " "
425                       << " is not of type unsigned short, ignoring.");
426       cdtiArray = nullptr;
427     }
428   }
429 
430   inPts = input->GetPoints();
431   inVectors = pd->GetVectors();
432   inNormals = pd->GetNormals();
433   inCellVectors = cd->GetVectors();
434   inCellNormals = cd->GetNormals();
435 
436   if (!inPts)
437   {
438     vtkErrorMacro(<< "No input data");
439     return 1;
440   }
441 
442   numPts = inPts->GetNumberOfPoints();
443   numCells = input->GetNumberOfCells();
444 
445   newPts = vtkPoints::New();
446   newPts->Allocate(numPts);
447   if (inVectors)
448   {
449     newVectors = vtkFloatArray::New();
450     newVectors->SetNumberOfComponents(3);
451     newVectors->Allocate(3 * numPts);
452   }
453   if (inNormals)
454   {
455     newNormals = vtkFloatArray::New();
456     newNormals->SetNumberOfComponents(3);
457     newNormals->Allocate(3 * numPts);
458   }
459 
460   this->UpdateProgress(.2);
461   // Loop over all points, updating position
462   //
463 
464   // since we may be doing multiple transforms, we must duplicate
465   // work done in vtkTransform
466 
467   // -------------------------- POINT DATA -------------------------------
468   if (pdArray != nullptr)
469   {
470     transformIndices = nullptr;
471     // do points
472     for (p = 0; p < numPts; p++)
473     {
474       // -------- points init ---------------
475       inPts->GetPoint(p, inPt);
476       if (this->AddInputValues)
477       {
478         cumPt[0] = inPt[0];
479         cumPt[1] = inPt[1];
480         cumPt[2] = inPt[2];
481       }
482       else
483       {
484         cumPt[0] = 0.0;
485         cumPt[1] = 0.0;
486         cumPt[2] = 0.0;
487       }
488       // -------- vectors init ---------------
489       if (inVectors)
490       {
491         inVectors->GetTuple(p, inVec);
492         if (this->AddInputValues)
493         {
494           cumVec[0] = inVec[0];
495           cumVec[1] = inVec[1];
496           cumVec[2] = inVec[2];
497         }
498         else
499         {
500           cumVec[0] = 0.0;
501           cumVec[1] = 0.0;
502           cumVec[2] = 0.0;
503         }
504       }
505       // -------- normals init ---------------
506       if (inNormals)
507       {
508         inNormals->GetTuple(p, inNorm);
509         if (this->AddInputValues)
510         {
511           cumNorm[0] = inNorm[0];
512           cumNorm[1] = inNorm[1];
513           cumNorm[2] = inNorm[2];
514         }
515         else
516         {
517           cumNorm[0] = 0.0;
518           cumNorm[1] = 0.0;
519           cumNorm[2] = 0.0;
520         }
521       }
522 
523       weights = reinterpret_cast<vtkFloatArray*>(pdArray)->GetPointer(p * pdComponents);
524 
525       if (tiArray != nullptr)
526       {
527         transformIndices =
528           reinterpret_cast<vtkUnsignedShortArray*>(tiArray)->GetPointer(p * pdComponents);
529       }
530 
531       // for each transform...
532       for (c = 0; c < pdComponents; c++)
533       {
534         if (transformIndices != nullptr)
535         {
536           tidx = transformIndices[c];
537         }
538         else
539         {
540           tidx = c;
541         }
542         if (tidx >= this->NumberOfTransforms || tidx < 0)
543         {
544           vtkWarningMacro(<< "transform index " << tidx << " outside valid range, ignoring");
545           continue;
546         }
547         thisWeight = weights[c];
548         if (this->Transforms[tidx] == nullptr || thisWeight == 0.0)
549         {
550           continue;
551         }
552 
553         if (linearPtMtx[tidx] != nullptr)
554         {
555           // -------------------- linear fast path ------------------------
556           LinearTransformPoint((double(*)[4])linearPtMtx[tidx], inPt, xformPt);
557 
558           if (inVectors)
559           {
560             LinearTransformVector((double(*)[4])linearPtMtx[tidx], inVec, xformVec);
561           }
562 
563           if (inNormals)
564           {
565             LinearTransformVector((double(*)[4])linearNormMtx[tidx].data(), inNorm, xformNorm);
566             // normalize below
567           }
568         }
569         else
570         {
571           // -------------------- general, slow path ------------------------
572           this->Transforms[tidx]->InternalTransformDerivative(inPt, xformPt, derivMatrix);
573           if (inVectors)
574           {
575             vtkMath::Multiply3x3(derivMatrix, inVec, xformVec);
576           }
577 
578           if (inNormals)
579           {
580             vtkMath::Transpose3x3(derivMatrix, derivMatrix);
581             vtkMath::LinearSolve3x3(derivMatrix, inNorm, xformNorm);
582             // normalize below
583           }
584         }
585 
586         // ------ accumulate the results into respective tuples -------
587         cumPt[0] += xformPt[0] * thisWeight;
588         cumPt[1] += xformPt[1] * thisWeight;
589         cumPt[2] += xformPt[2] * thisWeight;
590 
591         if (inVectors)
592         {
593           cumVec[0] += xformVec[0] * thisWeight;
594           cumVec[1] += xformVec[1] * thisWeight;
595           cumVec[2] += xformVec[2] * thisWeight;
596         }
597 
598         if (inNormals)
599         {
600           vtkMath::Normalize(xformNorm);
601           cumNorm[0] += xformNorm[0] * thisWeight;
602           cumNorm[1] += xformNorm[1] * thisWeight;
603           cumNorm[2] += xformNorm[2] * thisWeight;
604         }
605       }
606 
607       // assign components
608       newPts->InsertNextPoint(cumPt);
609 
610       if (inVectors)
611       {
612         newVectors->InsertNextTuple(cumVec);
613       }
614 
615       if (inNormals)
616       {
617         // normalize normal again
618         vtkMath::Normalize(cumNorm);
619         newNormals->InsertNextTuple(cumNorm);
620       }
621     }
622   }
623 
624   this->UpdateProgress(.6);
625 
626   // -------------------------- CELL DATA -------------------------------
627 
628   // can only work on cell data if the transforms are all linear
629   if (cdArray != nullptr && allLinear)
630   {
631     if (inCellVectors)
632     {
633       newCellVectors = vtkFloatArray::New();
634       newCellVectors->SetNumberOfComponents(3);
635       newCellVectors->Allocate(3 * numCells);
636     }
637     if (inCellNormals)
638     {
639       newCellNormals = vtkFloatArray::New();
640       newCellNormals->SetNumberOfComponents(3);
641       newCellNormals->Allocate(3 * numCells);
642     }
643     transformIndices = nullptr;
644     for (p = 0; p < numCells; p++)
645     {
646       // -------- normals init ---------------
647       if (inCellNormals)
648       {
649         inCellNormals->GetTuple(p, inNorm);
650         if (this->AddInputValues)
651         {
652           for (i = 0; i < 3; i++)
653           {
654             cumNorm[i] = inNorm[i];
655           }
656         }
657         else
658         {
659           for (i = 0; i < 3; i++)
660           {
661             cumNorm[i] = 0.0;
662           }
663         }
664       }
665       // -------- vectors init ---------------
666       if (inVectors)
667       {
668         inVectors->GetTuple(p, inVec);
669         if (this->AddInputValues)
670         {
671           for (i = 0; i < 3; i++)
672           {
673             cumVec[i] = inVec[i];
674           }
675         }
676         else
677         {
678           for (i = 0; i < 3; i++)
679           {
680             cumVec[i] = 0.0;
681           }
682         }
683       }
684 
685       weights = reinterpret_cast<vtkFloatArray*>(cdArray)->GetPointer(p * cdComponents);
686       if (cdtiArray != nullptr)
687       {
688         transformIndices =
689           reinterpret_cast<vtkUnsignedShortArray*>(cdtiArray)->GetPointer(p * cdComponents);
690       }
691 
692       // for each transform...
693       for (c = 0; c < cdComponents; c++)
694       {
695         if (transformIndices != nullptr)
696         {
697           tidx = transformIndices[c];
698         }
699         else
700         {
701           tidx = c;
702         }
703         if (tidx >= this->NumberOfTransforms || tidx < 0)
704         {
705           vtkWarningMacro(<< "transform index " << tidx << " outside valid range, ignoring");
706           continue;
707         }
708         thisWeight = weights[c];
709         if (linearPtMtx[tidx] == nullptr || thisWeight == 0.0)
710         {
711           continue;
712         }
713 
714         if (inCellNormals)
715         {
716           LinearTransformVector((double(*)[4])linearNormMtx[tidx].data(), inNorm, xformNorm);
717 
718           vtkMath::Normalize(xformNorm);
719           cumNorm[0] += xformNorm[0] * thisWeight;
720           cumNorm[1] += xformNorm[1] * thisWeight;
721           cumNorm[2] += xformNorm[2] * thisWeight;
722         }
723 
724         if (inVectors)
725         {
726           LinearTransformVector((double(*)[4])linearPtMtx[tidx], inVec, xformVec);
727           cumVec[0] += xformVec[0] * thisWeight;
728           cumVec[1] += xformVec[1] * thisWeight;
729           cumVec[2] += xformVec[2] * thisWeight;
730         }
731       }
732 
733       if (inCellNormals)
734       {
735         // normalize normal again
736         vtkMath::Normalize(cumNorm);
737         newCellNormals->InsertNextTuple(cumNorm);
738       }
739 
740       if (inCellVectors)
741       {
742         newCellVectors->InsertNextTuple(cumVec);
743       }
744     }
745   }
746 
747   this->UpdateProgress(0.8);
748 
749   // Update ourselves and release memory
750   //
751   output->SetPoints(newPts);
752   newPts->Delete();
753 
754   if (newNormals)
755   {
756     outPD->SetNormals(newNormals);
757     outPD->CopyNormalsOff();
758     newNormals->Delete();
759   }
760 
761   if (newVectors)
762   {
763     outPD->SetVectors(newVectors);
764     outPD->CopyVectorsOff();
765     newVectors->Delete();
766   }
767 
768   if (newCellNormals)
769   {
770     outCD->SetNormals(newCellNormals);
771     outCD->CopyNormalsOff();
772     newCellNormals->Delete();
773   }
774 
775   if (newCellVectors)
776   {
777     outCD->SetVectors(newCellVectors);
778     outCD->CopyVectorsOff();
779     newCellVectors->Delete();
780   }
781 
782   outPD->PassData(pd);
783   outCD->PassData(cd);
784 
785   return 1;
786 }
787 
788 //------------------------------------------------------------------------------
GetMTime()789 vtkMTimeType vtkWeightedTransformFilter::GetMTime()
790 {
791   int i;
792   vtkMTimeType mTime = this->MTime.GetMTime();
793   vtkMTimeType transMTime;
794 
795   if (this->Transforms)
796   {
797     for (i = 0; i < this->NumberOfTransforms; i++)
798     {
799       if (this->Transforms[i])
800       {
801         transMTime = this->Transforms[i]->GetMTime();
802         mTime = (transMTime > mTime ? transMTime : mTime);
803       }
804     }
805   }
806 
807   return mTime;
808 }
809 
810 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)811 void vtkWeightedTransformFilter::PrintSelf(ostream& os, vtkIndent indent)
812 {
813   int i;
814   this->Superclass::PrintSelf(os, indent);
815 
816   os << indent << "NumberOfTransforms: " << this->NumberOfTransforms << "\n";
817   for (i = 0; i < this->NumberOfTransforms; i++)
818   {
819     os << indent << "Transform " << i << ": " << this->Transforms[i] << "\n";
820   }
821   os << indent << "AddInputValues: " << (this->AddInputValues ? "On" : "Off") << "\n";
822   os << indent << "WeightArray: " << (this->WeightArray ? this->WeightArray : "(none)") << "\n";
823   os << indent << "CellDataWeightArray: "
824      << (this->CellDataWeightArray ? this->CellDataWeightArray : "(none)") << "\n";
825   os << indent << "TransformIndexArray: "
826      << (this->TransformIndexArray ? this->TransformIndexArray : "(none)") << "\n";
827   os << indent << "CellDataTransformIndexArray: "
828      << (this->CellDataTransformIndexArray ? this->CellDataTransformIndexArray : "(none)") << "\n";
829 }
830