1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkDataSetAttributes.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 "vtkDataSetAttributes.h"
16 
17 #include "vtkArrayDispatch.h"
18 #include "vtkArrayIteratorIncludes.h"
19 #include "vtkDataArrayRange.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkStructuredExtent.h"
22 
23 #include <vector>
24 
25 vtkStandardNewMacro(vtkDataSetAttributes);
26 vtkStandardExtendedNewMacro(vtkDataSetAttributes);
27 //------------------------------------------------------------------------------
28 const char vtkDataSetAttributes::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][19] = {
29   "Scalars",
30   "Vectors",
31   "Normals",
32   "TCoords",
33   "Tensors",
34   "GlobalIds",
35   "PedigreeIds",
36   "EdgeFlag",
37   "Tangents",
38   "RationalWeights",
39   "HigherOrderDegrees",
40 };
41 
42 const char vtkDataSetAttributes::LongAttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][42] = {
43   "vtkDataSetAttributes::SCALARS",
44   "vtkDataSetAttributes::VECTORS",
45   "vtkDataSetAttributes::NORMALS",
46   "vtkDataSetAttributes::TCOORDS",
47   "vtkDataSetAttributes::TENSORS",
48   "vtkDataSetAttributes::GLOBALIDS",
49   "vtkDataSetAttributes::PEDIGREEIDS",
50   "vtkDataSetAttributes::EDGEFLAG",
51   "vtkDataSetAttributes::TANGENTS",
52   "vtkDataSetAttributes::RATIONALWEIGHTS",
53   "vtkDataSetAttributes::HIGHERORDERDEGREES",
54 };
55 
56 //------------------------------------------------------------------------------
57 // Construct object with copying turned on for all data.
vtkDataSetAttributes()58 vtkDataSetAttributes::vtkDataSetAttributes()
59 {
60   int attributeType;
61   for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
62   {
63     this->AttributeIndices[attributeType] = -1;
64     this->CopyAttributeFlags[COPYTUPLE][attributeType] = 1;
65     this->CopyAttributeFlags[INTERPOLATE][attributeType] = 1;
66     this->CopyAttributeFlags[PASSDATA][attributeType] = 1;
67   }
68 
69   // Global IDs should not be interpolated because they are labels, not "numbers"
70   // Global IDs should not be copied either, unless doing so preserves meaning.
71   // Passing through is usually OK because it is 1:1.
72   this->CopyAttributeFlags[COPYTUPLE][GLOBALIDS] = 0;
73   this->CopyAttributeFlags[INTERPOLATE][GLOBALIDS] = 0;
74 
75   // Pedigree IDs should not be interpolated because they are labels, not "numbers"
76   // Pedigree IDs may be copied since they do not require 1:1 mapping.
77   this->CopyAttributeFlags[INTERPOLATE][PEDIGREEIDS] = 0;
78 
79   this->TargetIndices = nullptr;
80 }
81 
82 //------------------------------------------------------------------------------
83 // Destructor for the vtkDataSetAttributes objects.
~vtkDataSetAttributes()84 vtkDataSetAttributes::~vtkDataSetAttributes()
85 {
86   this->Initialize();
87   delete[] this->TargetIndices;
88   this->TargetIndices = nullptr;
89 }
90 
91 //------------------------------------------------------------------------------
92 // Turn on copying of all data.
CopyAllOn(int ctype)93 void vtkDataSetAttributes::CopyAllOn(int ctype)
94 {
95   this->vtkFieldData::CopyAllOn();
96   this->SetCopyScalars(1, ctype);
97   this->SetCopyVectors(1, ctype);
98   this->SetCopyNormals(1, ctype);
99   this->SetCopyTCoords(1, ctype);
100   this->SetCopyTensors(1, ctype);
101   this->SetCopyGlobalIds(1, ctype);
102   this->SetCopyPedigreeIds(1, ctype);
103   this->SetCopyTangents(1, ctype);
104   this->SetCopyRationalWeights(1, ctype);
105   this->SetCopyHigherOrderDegrees(1, ctype);
106 }
107 
108 //------------------------------------------------------------------------------
109 // Turn off copying of all data.
CopyAllOff(int ctype)110 void vtkDataSetAttributes::CopyAllOff(int ctype)
111 {
112   this->vtkFieldData::CopyAllOff();
113   this->SetCopyScalars(0, ctype);
114   this->SetCopyVectors(0, ctype);
115   this->SetCopyNormals(0, ctype);
116   this->SetCopyTCoords(0, ctype);
117   this->SetCopyTensors(0, ctype);
118   this->SetCopyGlobalIds(0, ctype);
119   this->SetCopyPedigreeIds(0, ctype);
120   this->SetCopyTangents(0, ctype);
121   this->SetCopyRationalWeights(0, ctype);
122   this->SetCopyHigherOrderDegrees(0, ctype);
123 }
124 
125 //------------------------------------------------------------------------------
126 // Deep copy of data (i.e., create new data arrays and
127 // copy from input data). Note that attribute data is
128 // not copied.
DeepCopy(vtkFieldData * fd)129 void vtkDataSetAttributes::DeepCopy(vtkFieldData* fd)
130 {
131   this->Initialize(); // free up memory
132 
133   vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd);
134   // If the source is a vtkDataSetAttributes
135   if (dsa)
136   {
137     int numArrays = fd->GetNumberOfArrays();
138     int attributeType, i;
139     vtkAbstractArray *data, *newData;
140 
141     // Allocate space for numArrays
142     this->AllocateArrays(numArrays);
143     for (i = 0; i < numArrays; i++)
144     {
145       data = fd->GetAbstractArray(i);
146       newData = data->NewInstance(); // instantiate same type of object
147       newData->DeepCopy(data);
148       newData->SetName(data->GetName());
149       this->AddArray(newData);
150       newData->Delete();
151     }
152     // Copy the copy flags
153     for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
154     {
155       // If an array is an attribute in the source, then mark it as a attribute
156       // in the clone as well.
157       this->AttributeIndices[attributeType] = dsa->AttributeIndices[attributeType];
158 
159       this->CopyAttributeFlags[COPYTUPLE][attributeType] =
160         dsa->CopyAttributeFlags[COPYTUPLE][attributeType];
161       this->CopyAttributeFlags[INTERPOLATE][attributeType] =
162         dsa->CopyAttributeFlags[INTERPOLATE][attributeType];
163       this->CopyAttributeFlags[PASSDATA][attributeType] =
164         dsa->CopyAttributeFlags[PASSDATA][attributeType];
165     }
166     this->CopyFlags(dsa);
167   }
168   // If the source is field data, do a field data copy
169   else
170   {
171     this->vtkFieldData::DeepCopy(fd);
172   }
173 }
174 
175 //------------------------------------------------------------------------------
176 // Shallow copy of data (i.e., use reference counting).
ShallowCopy(vtkFieldData * fd)177 void vtkDataSetAttributes::ShallowCopy(vtkFieldData* fd)
178 {
179   this->Initialize(); // free up memory
180 
181   vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd);
182   // If the source is a vtkDataSetAttributes
183   if (dsa)
184   {
185     int numArrays = fd->GetNumberOfArrays();
186     int attributeType, i;
187 
188     // Allocate space for numArrays
189     this->AllocateArrays(numArrays);
190     this->NumberOfActiveArrays = 0;
191     for (i = 0; i < numArrays; i++)
192     {
193       this->NumberOfActiveArrays++;
194       this->SetArray(i, fd->GetAbstractArray(i));
195     }
196 
197     // Copy the copy flags
198     for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
199     {
200       // If an array is an attribute in the source, then mark it as a attribute
201       // in the clone as well.
202       this->AttributeIndices[attributeType] = dsa->AttributeIndices[attributeType];
203 
204       this->CopyAttributeFlags[COPYTUPLE][attributeType] =
205         dsa->CopyAttributeFlags[COPYTUPLE][attributeType];
206       this->CopyAttributeFlags[INTERPOLATE][attributeType] =
207         dsa->CopyAttributeFlags[INTERPOLATE][attributeType];
208       this->CopyAttributeFlags[PASSDATA][attributeType] =
209         dsa->CopyAttributeFlags[PASSDATA][attributeType];
210     }
211     this->CopyFlags(dsa);
212   }
213   // If the source is field data, do a field data copy
214   else
215   {
216     this->vtkFieldData::ShallowCopy(fd);
217   }
218 }
219 
220 //------------------------------------------------------------------------------
221 // Initialize all of the object's data to nullptr
InitializeFields()222 void vtkDataSetAttributes::InitializeFields()
223 {
224   this->vtkFieldData::InitializeFields();
225 
226   int attributeType;
227   for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
228   {
229     this->AttributeIndices[attributeType] = -1;
230     this->CopyAttributeFlags[COPYTUPLE][attributeType] = 1;
231     this->CopyAttributeFlags[INTERPOLATE][attributeType] = 1;
232     this->CopyAttributeFlags[PASSDATA][attributeType] = 1;
233   }
234   this->CopyAttributeFlags[COPYTUPLE][GLOBALIDS] = 0;
235   this->CopyAttributeFlags[INTERPOLATE][GLOBALIDS] = 0;
236 
237   this->CopyAttributeFlags[INTERPOLATE][PEDIGREEIDS] = 0;
238 }
239 
240 //------------------------------------------------------------------------------
241 // Initialize all of the object's data to nullptr
Initialize()242 void vtkDataSetAttributes::Initialize()
243 {
244   //
245   // We don't modify ourselves because the "ReleaseData" methods depend upon
246   // no modification when initialized.
247   //
248 
249   // Call superclass' Initialize()
250   this->vtkFieldData::Initialize();
251   //
252   // Free up any memory
253   // And don't forget to reset the attribute copy flags.
254   int attributeType;
255   for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
256   {
257     this->AttributeIndices[attributeType] = -1;
258     this->CopyAttributeFlags[COPYTUPLE][attributeType] = 1;
259     this->CopyAttributeFlags[INTERPOLATE][attributeType] = 1;
260     this->CopyAttributeFlags[PASSDATA][attributeType] = 1;
261   }
262   this->CopyAttributeFlags[COPYTUPLE][GLOBALIDS] = 0;
263   this->CopyAttributeFlags[INTERPOLATE][GLOBALIDS] = 0;
264 
265   this->CopyAttributeFlags[INTERPOLATE][PEDIGREEIDS] = 0;
266 }
267 
268 //------------------------------------------------------------------------------
269 // This method is used to determine which arrays
270 // will be copied to this object
ComputeRequiredArrays(vtkDataSetAttributes * pd,int ctype)271 vtkFieldData::BasicIterator vtkDataSetAttributes::ComputeRequiredArrays(
272   vtkDataSetAttributes* pd, int ctype)
273 {
274   if ((ctype < COPYTUPLE) || (ctype > PASSDATA))
275   {
276     vtkErrorMacro("Must call compute required with COPYTUPLE, INTERPOLATE or PASSDATA");
277     ctype = COPYTUPLE;
278   }
279 
280   // We need to do some juggling to find the number of arrays
281   // which will be passed.
282 
283   // First, find the number of arrays to be copied because they
284   // are in the list of _fields_ to be copied (and the actual data
285   // pointer is non-nullptr). Also, we keep those indices in a list.
286   int* copyFlags = new int[pd->GetNumberOfArrays()];
287   int index, i, numArrays = 0;
288   for (i = 0; i < pd->GetNumberOfArrays(); i++)
289   {
290     const char* arrayName = pd->GetArrayName(i);
291     // If there is no blocker for the given array
292     // and both CopyAllOff and CopyOn for that array are not true
293     if ((this->GetFlag(arrayName) != 0) &&
294       !(this->DoCopyAllOff && (this->GetFlag(arrayName) != 1)) && pd->GetAbstractArray(i))
295     {
296       // Cannot interpolate idtype arrays
297       if (ctype != INTERPOLATE || pd->GetAbstractArray(i)->GetDataType() != VTK_ID_TYPE)
298       {
299         copyFlags[numArrays] = i;
300         numArrays++;
301       }
302     }
303   }
304 
305   // Next, we check the arrays to be copied because they are one of
306   // the _attributes_ to be copied (and the data array in non-nullptr).
307   // We make sure that we don't count anything twice.
308   int alreadyCopied;
309   int attributeType, j;
310   for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
311   {
312     index = pd->AttributeIndices[attributeType];
313     int flag = this->GetFlag(pd->GetArrayName(index));
314     // If this attribute is to be copied
315     if (this->CopyAttributeFlags[ctype][attributeType] && flag)
316     {
317       // Find out if it is also in the list of fields to be copied
318       // Since attributes can only be vtkDataArray, we use GetArray() call.
319       if (pd->GetArray(index))
320       {
321         alreadyCopied = 0;
322         for (i = 0; i < numArrays; i++)
323         {
324           if (index == copyFlags[i])
325           {
326             alreadyCopied = 1;
327           }
328         }
329         // If not, increment the number of arrays to be copied.
330         if (!alreadyCopied)
331         {
332           // Cannot interpolate idtype arrays
333           if (ctype != INTERPOLATE || pd->GetArray(index)->GetDataType() != VTK_ID_TYPE)
334           {
335             copyFlags[numArrays] = index;
336             numArrays++;
337           }
338         }
339       }
340     }
341     // If it is not to be copied and it is in the list (from the
342     // previous pass), remove it
343     else
344     {
345       for (i = 0; i < numArrays; i++)
346       {
347         if (index == copyFlags[i])
348         {
349           for (j = i; j < numArrays - 1; j++)
350           {
351             copyFlags[j] = copyFlags[j + 1];
352           }
353           numArrays--;
354           i--;
355         }
356       }
357     }
358   }
359 
360   vtkFieldData::BasicIterator it(copyFlags, numArrays);
361   delete[] copyFlags;
362   return it;
363 }
364 
365 //------------------------------------------------------------------------------
366 // Pass entire arrays of input data through to output. Obey the "copy"
367 // flags.
PassData(vtkFieldData * fd)368 void vtkDataSetAttributes::PassData(vtkFieldData* fd)
369 {
370   if (!fd)
371   {
372     return;
373   }
374 
375   vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd);
376 
377   if (dsa)
378   {
379     // Create an iterator to iterate over the fields which will
380     // be passed, i.e. fields which are either:
381     // 1> in the list of _fields_ to be copied or
382     // 2> in the list of _attributes_ to be copied.
383     // Note that nullptr data arrays are not copied
384 
385     vtkFieldData::BasicIterator it = this->ComputeRequiredArrays(dsa, PASSDATA);
386 
387     if (it.GetListSize() > this->NumberOfArrays)
388     {
389       this->AllocateArrays(it.GetListSize());
390     }
391     if (it.GetListSize() == 0)
392     {
393       return;
394     }
395 
396     // Since we are replacing, remove old attributes
397     int attributeType; // will change//
398     for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
399     {
400       if (this->CopyAttributeFlags[PASSDATA][attributeType])
401       {
402         this->RemoveArray(this->AttributeIndices[attributeType]);
403         this->AttributeIndices[attributeType] = -1;
404       }
405     }
406 
407     int arrayIndex;
408     for (const auto& i : it)
409     {
410       arrayIndex = this->AddArray(dsa->GetAbstractArray(i));
411       // If necessary, make the array an attribute
412       if (((attributeType = dsa->IsArrayAnAttribute(i)) != -1) &&
413         this->CopyAttributeFlags[PASSDATA][attributeType])
414       {
415         this->SetActiveAttribute(arrayIndex, attributeType);
416       }
417     }
418   }
419   else
420   {
421     this->vtkFieldData::PassData(fd);
422   }
423 }
424 
425 //------------------------------------------------------------------------------
426 namespace
427 {
428 struct CopyStructuredDataWorker
429 {
430   const int* OutExt;
431   const int* InExt;
432 
CopyStructuredDataWorker__anon64e9ea3c0111::CopyStructuredDataWorker433   CopyStructuredDataWorker(const int* outExt, const int* inExt)
434     : OutExt(outExt)
435     , InExt(inExt)
436   {
437   }
438 
439   template <typename Array1T, typename Array2T>
operator ()__anon64e9ea3c0111::CopyStructuredDataWorker440   void operator()(Array1T* dstArray, Array2T* srcArray)
441   {
442     // Give the compiler a hand -- allow optimizations that require both arrays
443     // to have the same stride.
444     VTK_ASSUME(srcArray->GetNumberOfComponents() == dstArray->GetNumberOfComponents());
445 
446     // Create some tuple ranges to simplify optimized copying:
447     const auto srcTuples = vtk::DataArrayTupleRange(srcArray);
448     auto dstTuples = vtk::DataArrayTupleRange(dstArray);
449 
450     if (vtkStructuredExtent::Smaller(this->OutExt, this->InExt))
451     {
452       // get outExt relative to the inExt to keep the logic simple. This assumes
453       // that outExt is a subset of the inExt.
454       const int relOutExt[6] = {
455         this->OutExt[0] - this->InExt[0],
456         this->OutExt[1] - this->InExt[0],
457         this->OutExt[2] - this->InExt[2],
458         this->OutExt[3] - this->InExt[2],
459         this->OutExt[4] - this->InExt[4],
460         this->OutExt[5] - this->InExt[4],
461       };
462 
463       const int dims[3] = {
464         this->InExt[1] - this->InExt[0] + 1,
465         this->InExt[3] - this->InExt[2] + 1,
466         this->InExt[5] - this->InExt[4] + 1,
467       };
468 
469       auto dstTupleIter = dstTuples.begin();
470       for (int outz = relOutExt[4]; outz <= relOutExt[5]; ++outz)
471       {
472         const vtkIdType zfactor = static_cast<vtkIdType>(outz) * dims[1];
473         for (int outy = relOutExt[2]; outy <= relOutExt[3]; ++outy)
474         {
475           const vtkIdType yfactor = (zfactor + outy) * dims[0];
476           for (int outx = relOutExt[0]; outx <= relOutExt[1]; ++outx)
477           {
478             const vtkIdType inTupleIdx = yfactor + outx;
479             *dstTupleIter++ = srcTuples[inTupleIdx];
480           }
481         }
482       }
483     }
484     else
485     {
486       int writeExt[6];
487       memcpy(writeExt, this->OutExt, 6 * sizeof(int));
488       vtkStructuredExtent::Clamp(writeExt, this->InExt);
489 
490       const vtkIdType inDims[3] = { this->InExt[1] - this->InExt[0] + 1,
491         this->InExt[3] - this->InExt[2] + 1, this->InExt[5] - this->InExt[4] + 1 };
492       const vtkIdType outDims[3] = { this->OutExt[1] - this->OutExt[0] + 1,
493         this->OutExt[3] - this->OutExt[2] + 1, this->OutExt[5] - this->OutExt[4] + 1 };
494 
495       for (int idz = writeExt[4]; idz <= writeExt[5]; ++idz)
496       {
497         const vtkIdType inTupleId1 = (idz - this->InExt[4]) * inDims[0] * inDims[1];
498         const vtkIdType outTupleId1 = (idz - this->OutExt[4]) * outDims[0] * outDims[1];
499         for (int idy = writeExt[2]; idy <= writeExt[3]; ++idy)
500         {
501           const vtkIdType inTupleId2 = inTupleId1 + (idy - this->InExt[2]) * inDims[0];
502           const vtkIdType outTupleId2 = outTupleId1 + (idy - this->OutExt[2]) * outDims[0];
503           for (int idx = writeExt[0]; idx <= writeExt[1]; ++idx)
504           {
505             const vtkIdType inTupleIdx = inTupleId2 + idx - this->InExt[0];
506             const vtkIdType outTupleIdx = outTupleId2 + idx - this->OutExt[0];
507 
508             dstTuples[outTupleIdx] = srcTuples[inTupleIdx];
509           }
510         }
511       }
512     }
513 
514     dstArray->DataChanged();
515   }
516 };
517 
518 //------------------------------------------------------------------------------
519 // Handle vtkAbstractArrays that aren't vtkDataArrays.
520 template <class iterT>
vtkDataSetAttributesCopyValues(iterT * destIter,const int * outExt,vtkIdType outIncs[3],iterT * srcIter,const int * inExt,vtkIdType inIncs[3])521 void vtkDataSetAttributesCopyValues(iterT* destIter, const int* outExt, vtkIdType outIncs[3],
522   iterT* srcIter, const int* inExt, vtkIdType inIncs[3])
523 {
524   int data_type_size = srcIter->GetArray()->GetDataTypeSize();
525   vtkIdType rowLength = outIncs[1];
526   unsigned char* inPtr;
527   unsigned char* outPtr;
528   unsigned char* inZPtr;
529   unsigned char* outZPtr;
530 
531   // Get the starting input pointer.
532   inZPtr = static_cast<unsigned char*>(srcIter->GetArray()->GetVoidPointer(0));
533   // Shift to the start of the subextent.
534   inZPtr += (outExt[0] - inExt[0]) * inIncs[0] * data_type_size +
535     (outExt[2] - inExt[2]) * inIncs[1] * data_type_size +
536     (outExt[4] - inExt[4]) * inIncs[2] * data_type_size;
537 
538   // Get output pointer.
539   outZPtr = static_cast<unsigned char*>(destIter->GetArray()->GetVoidPointer(0));
540 
541   // Loop over z axis.
542   for (int zIdx = outExt[4]; zIdx <= outExt[5]; ++zIdx)
543   {
544     inPtr = inZPtr;
545     outPtr = outZPtr;
546     for (int yIdx = outExt[2]; yIdx <= outExt[3]; ++yIdx)
547     {
548       memcpy(outPtr, inPtr, rowLength * data_type_size);
549       inPtr += inIncs[1] * data_type_size;
550       outPtr += outIncs[1] * data_type_size;
551     }
552     inZPtr += inIncs[2] * data_type_size;
553     outZPtr += outIncs[2] * data_type_size;
554   }
555 }
556 
557 //------------------------------------------------------------------------------
558 // Specialize for vtkStringArray.
559 template <>
vtkDataSetAttributesCopyValues(vtkArrayIteratorTemplate<vtkStdString> * destIter,const int * outExt,vtkIdType outIncs[3],vtkArrayIteratorTemplate<vtkStdString> * srcIter,const int * inExt,vtkIdType inIncs[3])560 void vtkDataSetAttributesCopyValues(vtkArrayIteratorTemplate<vtkStdString>* destIter,
561   const int* outExt, vtkIdType outIncs[3], vtkArrayIteratorTemplate<vtkStdString>* srcIter,
562   const int* inExt, vtkIdType inIncs[3])
563 {
564   vtkIdType inZIndex = (outExt[0] - inExt[0]) * inIncs[0] + (outExt[2] - inExt[2]) * inIncs[1] +
565     (outExt[4] - inExt[4]) * inIncs[2];
566 
567   vtkIdType outZIndex = 0;
568   vtkIdType rowLength = outIncs[1];
569 
570   for (int zIdx = outExt[4]; zIdx <= outExt[5]; ++zIdx)
571   {
572     vtkIdType inIndex = inZIndex;
573     vtkIdType outIndex = outZIndex;
574     for (int yIdx = outExt[2]; yIdx <= outExt[3]; ++yIdx)
575     {
576       for (int xIdx = 0; xIdx < rowLength; ++xIdx)
577       {
578         destIter->GetValue(outIndex + xIdx) = srcIter->GetValue(inIndex + xIdx);
579       }
580       inIndex += inIncs[1];
581       outIndex += outIncs[1];
582     }
583     inZIndex += inIncs[2];
584     outZIndex += outIncs[2];
585   }
586 }
587 
588 } // end anon namespace
589 
590 //------------------------------------------------------------------------------
591 // This is used in the imaging pipeline for copying arrays.
592 // CopyAllocate needs to be called before this method.
CopyStructuredData(vtkDataSetAttributes * fromPd,const int * inExt,const int * outExt,bool setSize)593 void vtkDataSetAttributes::CopyStructuredData(
594   vtkDataSetAttributes* fromPd, const int* inExt, const int* outExt, bool setSize)
595 {
596   for (const auto& i : this->RequiredArrays)
597   {
598     vtkAbstractArray* inArray = fromPd->Data[i];
599     vtkAbstractArray* outArray = this->Data[this->TargetIndices[i]];
600     vtkIdType inIncs[3];
601     vtkIdType outIncs[3];
602     vtkIdType zIdx;
603 
604     // Compute increments
605     inIncs[0] = inArray->GetNumberOfComponents();
606     inIncs[1] = inIncs[0] * (inExt[1] - inExt[0] + 1);
607     inIncs[2] = inIncs[1] * (inExt[3] - inExt[2] + 1);
608     outIncs[0] = inIncs[0];
609     outIncs[1] = outIncs[0] * (outExt[1] - outExt[0] + 1);
610     outIncs[2] = outIncs[1] * (outExt[3] - outExt[2] + 1);
611 
612     // Make sure the input extents match the actual array lengths.
613     zIdx = inIncs[2] / inIncs[0] * (inExt[5] - inExt[4] + 1);
614     if (inArray->GetNumberOfTuples() != zIdx)
615     {
616       vtkErrorMacro("Input extent (" << inExt[0] << ", " << inExt[1] << ", " << inExt[2] << ", "
617                                      << inExt[3] << ", " << inExt[4] << ", " << inExt[5]
618                                      << ") does not match array length: " << zIdx);
619       // Skip copying this array.
620       continue;
621     }
622     // Make sure the output extents match the actual array lengths.
623     zIdx = outIncs[2] / outIncs[0] * (outExt[5] - outExt[4] + 1);
624     if (outArray->GetNumberOfTuples() != zIdx && setSize)
625     {
626       // The "CopyAllocate" method only sets the size, not the number of tuples.
627       outArray->SetNumberOfTuples(zIdx);
628     }
629 
630     // We get very little performance improvement from this, but we'll leave the
631     // legacy code around until we've done through benchmarking.
632     vtkDataArray* inDA = vtkArrayDownCast<vtkDataArray>(inArray);
633     vtkDataArray* outDA = vtkArrayDownCast<vtkDataArray>(outArray);
634     if (!inDA || !outDA) // String array, etc
635     {
636       vtkArrayIterator* srcIter = inArray->NewIterator();
637       vtkArrayIterator* destIter = outArray->NewIterator();
638       switch (inArray->GetDataType())
639       {
640         vtkArrayIteratorTemplateMacro(vtkDataSetAttributesCopyValues(static_cast<VTK_TT*>(destIter),
641           outExt, outIncs, static_cast<VTK_TT*>(srcIter), inExt, inIncs));
642       }
643       srcIter->Delete();
644       destIter->Delete();
645     }
646     else
647     {
648       CopyStructuredDataWorker worker(outExt, inExt);
649       if (!vtkArrayDispatch::Dispatch2SameValueType::Execute(outDA, inDA, worker))
650       {
651         // Fallback to vtkDataArray API (e.g. vtkBitArray):
652         worker(outDA, inDA);
653       }
654     }
655   }
656 }
657 
658 //------------------------------------------------------------------------------
SetupForCopy(vtkDataSetAttributes * pd)659 void vtkDataSetAttributes::SetupForCopy(vtkDataSetAttributes* pd)
660 {
661   this->InternalCopyAllocate(pd, COPYTUPLE, 0, 0, false, false);
662 }
663 
664 //------------------------------------------------------------------------------
665 // Allocates point data for point-by-point (or cell-by-cell) copy operation.
666 // If sze=0, then use the input DataSetAttributes to create (i.e., find
667 // initial size of) new objects; otherwise use the sze variable.
InternalCopyAllocate(vtkDataSetAttributes * pd,int ctype,vtkIdType sze,vtkIdType ext,int shallowCopyArrays,bool createNewArrays)668 void vtkDataSetAttributes::InternalCopyAllocate(vtkDataSetAttributes* pd, int ctype, vtkIdType sze,
669   vtkIdType ext, int shallowCopyArrays, bool createNewArrays)
670 {
671   vtkAbstractArray* newAA;
672 
673   // Create various point data depending upon input
674   //
675   if (!pd)
676   {
677     return;
678   }
679 
680   if ((ctype < COPYTUPLE) || (ctype > PASSDATA))
681   {
682     return;
683   }
684 
685   this->RequiredArrays = this->ComputeRequiredArrays(pd, ctype);
686   if (this->RequiredArrays.GetListSize() == 0)
687   {
688     return;
689   }
690   delete[] this->TargetIndices;
691   this->TargetIndices = new int[pd->GetNumberOfArrays()];
692   for (int i = 0; i < pd->GetNumberOfArrays(); i++)
693   {
694     this->TargetIndices[i] = -1;
695   }
696 
697   vtkAbstractArray* aa = nullptr;
698   int attributeType;
699 
700   // If we are not copying on self
701   if ((pd != this) && createNewArrays)
702   {
703     for (const auto& i : this->RequiredArrays)
704     {
705       // Create all required arrays
706       aa = pd->GetAbstractArray(i);
707       if (shallowCopyArrays)
708       {
709         newAA = aa;
710       }
711       else
712       {
713         newAA = aa->NewInstance();
714         newAA->SetNumberOfComponents(aa->GetNumberOfComponents());
715         newAA->CopyComponentNames(aa);
716         newAA->SetName(aa->GetName());
717         if (aa->HasInformation())
718         {
719           newAA->CopyInformation(aa->GetInformation(), /*deep=*/1);
720         }
721         if (sze > 0)
722         {
723           newAA->Allocate(sze * aa->GetNumberOfComponents(), ext);
724         }
725         else
726         {
727           newAA->Allocate(aa->GetNumberOfTuples());
728         }
729         vtkDataArray* newDA = vtkArrayDownCast<vtkDataArray>(newAA);
730         if (newDA)
731         {
732           vtkDataArray* da = vtkArrayDownCast<vtkDataArray>(aa);
733           newDA->SetLookupTable(da->GetLookupTable());
734         }
735       }
736       this->TargetIndices[i] = this->AddArray(newAA);
737       // If necessary, make the array an attribute
738       if (((attributeType = pd->IsArrayAnAttribute(i)) != -1) &&
739         this->CopyAttributeFlags[ctype][attributeType])
740       {
741         this->CopyAttributeFlags[ctype][attributeType] =
742           pd->CopyAttributeFlags[ctype][attributeType];
743         this->SetActiveAttribute(this->TargetIndices[i], attributeType);
744       }
745       if (!shallowCopyArrays)
746       {
747         newAA->Delete();
748       }
749     }
750   }
751   else if (pd == this)
752   {
753     // If copying on self, resize the arrays and initialize
754     // TargetIndices
755     for (const auto& i : this->RequiredArrays)
756     {
757       aa = pd->GetAbstractArray(i);
758       aa->Resize(sze);
759       this->TargetIndices[i] = i;
760     }
761   }
762   else
763   {
764     // All we are asked to do is create a mapping.
765     // Here we assume that arrays are the same and ordered
766     // the same way.
767     for (const auto& i : this->RequiredArrays)
768     {
769       this->TargetIndices[i] = i;
770     }
771   }
772 }
773 
774 //------------------------------------------------------------------------------
RemoveArray(int index)775 void vtkDataSetAttributes::RemoveArray(int index)
776 {
777   if ((index < 0) || (index >= this->NumberOfActiveArrays))
778   {
779     return;
780   }
781   this->Superclass::RemoveArray(index);
782 
783   // Adjust attribute types
784   int attributeType;
785   for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
786   {
787     if (this->AttributeIndices[attributeType] == index)
788     {
789       this->AttributeIndices[attributeType] = -1;
790     }
791     else if (this->AttributeIndices[attributeType] > index)
792     {
793       this->AttributeIndices[attributeType]--;
794     }
795   }
796 }
797 
798 //------------------------------------------------------------------------------
799 // Copy the attribute data from one id to another. Make sure CopyAllocate() has
800 // been invoked before using this method.
CopyData(vtkDataSetAttributes * fromPd,vtkIdType fromId,vtkIdType toId)801 void vtkDataSetAttributes::CopyData(vtkDataSetAttributes* fromPd, vtkIdType fromId, vtkIdType toId)
802 {
803   for (const auto& i : this->RequiredArrays)
804   {
805     this->CopyTuple(fromPd->Data[i], this->Data[this->TargetIndices[i]], fromId, toId);
806   }
807 }
808 
809 //------------------------------------------------------------------------------
CopyData(vtkDataSetAttributes * fromPd,vtkIdList * fromIds,vtkIdList * toIds)810 void vtkDataSetAttributes::CopyData(
811   vtkDataSetAttributes* fromPd, vtkIdList* fromIds, vtkIdList* toIds)
812 {
813   for (const auto& i : this->RequiredArrays)
814   {
815     this->CopyTuples(fromPd->Data[i], this->Data[this->TargetIndices[i]], fromIds, toIds);
816   }
817 }
818 
819 //------------------------------------------------------------------------------
CopyData(vtkDataSetAttributes * fromPd,vtkIdType dstStart,vtkIdType n,vtkIdType srcStart)820 void vtkDataSetAttributes::CopyData(
821   vtkDataSetAttributes* fromPd, vtkIdType dstStart, vtkIdType n, vtkIdType srcStart)
822 {
823   for (const auto& i : this->RequiredArrays)
824   {
825     this->CopyTuples(fromPd->Data[i], this->Data[this->TargetIndices[i]], dstStart, n, srcStart);
826   }
827 }
828 
829 //------------------------------------------------------------------------------
CopyAllocate(vtkDataSetAttributes * pd,vtkIdType sze,vtkIdType ext,int shallowCopyArrays)830 void vtkDataSetAttributes::CopyAllocate(
831   vtkDataSetAttributes* pd, vtkIdType sze, vtkIdType ext, int shallowCopyArrays)
832 {
833   this->InternalCopyAllocate(pd, COPYTUPLE, sze, ext, shallowCopyArrays);
834 }
835 
836 // Initialize point interpolation method.
InterpolateAllocate(vtkDataSetAttributes * pd,vtkIdType sze,vtkIdType ext,int shallowCopyArrays)837 void vtkDataSetAttributes::InterpolateAllocate(
838   vtkDataSetAttributes* pd, vtkIdType sze, vtkIdType ext, int shallowCopyArrays)
839 {
840   this->InternalCopyAllocate(pd, INTERPOLATE, sze, ext, shallowCopyArrays);
841 }
842 
843 //------------------------------------------------------------------------------
844 // Interpolate data from points and interpolation weights. Make sure that the
845 // method InterpolateAllocate() has been invoked before using this method.
InterpolatePoint(vtkDataSetAttributes * fromPd,vtkIdType toId,vtkIdList * ptIds,double * weights)846 void vtkDataSetAttributes::InterpolatePoint(
847   vtkDataSetAttributes* fromPd, vtkIdType toId, vtkIdList* ptIds, double* weights)
848 {
849   for (const auto& i : this->RequiredArrays)
850   {
851     vtkAbstractArray* fromArray = fromPd->Data[i];
852     vtkAbstractArray* toArray = this->Data[this->TargetIndices[i]];
853 
854     // check if the destination array needs nearest neighbor interpolation
855     int attributeIndex = this->IsArrayAnAttribute(this->TargetIndices[i]);
856     if (attributeIndex != -1 && this->CopyAttributeFlags[INTERPOLATE][attributeIndex] == 2)
857     {
858       vtkIdType numIds = ptIds->GetNumberOfIds();
859       vtkIdType maxId = ptIds->GetId(0);
860       vtkIdType maxWeight = 0.;
861       for (int j = 0; j < numIds; j++)
862       {
863         if (weights[j] > maxWeight)
864         {
865           maxWeight = weights[j];
866           maxId = ptIds->GetId(j);
867         }
868       }
869       toArray->InsertTuple(toId, maxId, fromArray);
870     }
871     else
872     {
873       toArray->InterpolateTuple(toId, ptIds, fromArray, weights);
874     }
875   } // for all arrays to interpolate
876 }
877 
878 //------------------------------------------------------------------------------
879 // Interpolate data from the two points p1,p2 (forming an edge) and an
880 // interpolation factor, t, along the edge. The weight ranges from (0,1),
881 // with t=0 located at p1. Make sure that the method InterpolateAllocate()
882 // has been invoked before using this method.
InterpolateEdge(vtkDataSetAttributes * fromPd,vtkIdType toId,vtkIdType p1,vtkIdType p2,double t)883 void vtkDataSetAttributes::InterpolateEdge(
884   vtkDataSetAttributes* fromPd, vtkIdType toId, vtkIdType p1, vtkIdType p2, double t)
885 {
886   for (const auto& i : this->RequiredArrays)
887   {
888     vtkAbstractArray* fromArray = fromPd->Data[i];
889     vtkAbstractArray* toArray = this->Data[this->TargetIndices[i]];
890 
891     // check if the destination array needs nearest neighbor interpolation
892     int attributeIndex = this->IsArrayAnAttribute(this->TargetIndices[i]);
893     if (attributeIndex != -1 && this->CopyAttributeFlags[INTERPOLATE][attributeIndex] == 2)
894     {
895       if (t < .5)
896       {
897         toArray->InsertTuple(toId, p1, fromArray);
898       }
899       else
900       {
901         toArray->InsertTuple(toId, p2, fromArray);
902       }
903     }
904     else
905     {
906       toArray->InterpolateTuple(toId, p1, fromArray, p2, fromArray, t);
907     }
908   }
909 }
910 
911 //------------------------------------------------------------------------------
912 // Interpolate data from the two points p1,p2 (forming an edge) and an
913 // interpolation factor, t, along the edge. The weight ranges from (0,1),
914 // with t=0 located at p1. Make sure that the method InterpolateAllocate()
915 // has been invoked before using this method.
InterpolateTime(vtkDataSetAttributes * from1,vtkDataSetAttributes * from2,vtkIdType id,double t)916 void vtkDataSetAttributes::InterpolateTime(
917   vtkDataSetAttributes* from1, vtkDataSetAttributes* from2, vtkIdType id, double t)
918 {
919   for (int attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
920   {
921     // If this attribute is to be copied
922     if (this->CopyAttributeFlags[INTERPOLATE][attributeType])
923     {
924       if (from1->GetAttribute(attributeType) && from2->GetAttribute(attributeType))
925       {
926         vtkAbstractArray* toArray = this->GetAttribute(attributeType);
927         // check if the destination array needs nearest neighbor interpolation
928         if (this->CopyAttributeFlags[INTERPOLATE][attributeType] == 2)
929         {
930           if (t < .5)
931           {
932             toArray->InsertTuple(id, id, from1->GetAttribute(attributeType));
933           }
934           else
935           {
936             toArray->InsertTuple(id, id, from2->GetAttribute(attributeType));
937           }
938         }
939         else
940         {
941           toArray->InterpolateTuple(
942             id, id, from1->GetAttribute(attributeType), id, from2->GetAttribute(attributeType), t);
943         }
944       }
945     }
946   }
947 }
948 
949 //------------------------------------------------------------------------------
950 // Copy a tuple of data from one data array to another. This method (and
951 // following ones) assume that the fromData and toData objects are of the
952 // same type, and have the same number of components. This is true if you
953 // invoke CopyAllocate() or InterpolateAllocate().
CopyTuple(vtkAbstractArray * fromData,vtkAbstractArray * toData,vtkIdType fromId,vtkIdType toId)954 void vtkDataSetAttributes::CopyTuple(
955   vtkAbstractArray* fromData, vtkAbstractArray* toData, vtkIdType fromId, vtkIdType toId)
956 {
957   toData->InsertTuple(toId, fromId, fromData);
958 }
959 
960 //------------------------------------------------------------------------------
CopyTuples(vtkAbstractArray * fromData,vtkAbstractArray * toData,vtkIdList * fromIds,vtkIdList * toIds)961 void vtkDataSetAttributes::CopyTuples(
962   vtkAbstractArray* fromData, vtkAbstractArray* toData, vtkIdList* fromIds, vtkIdList* toIds)
963 {
964   toData->InsertTuples(toIds, fromIds, fromData);
965 }
966 
967 //------------------------------------------------------------------------------
CopyTuples(vtkAbstractArray * fromData,vtkAbstractArray * toData,vtkIdType dstStart,vtkIdType n,vtkIdType srcStart)968 void vtkDataSetAttributes::CopyTuples(vtkAbstractArray* fromData, vtkAbstractArray* toData,
969   vtkIdType dstStart, vtkIdType n, vtkIdType srcStart)
970 {
971   toData->InsertTuples(dstStart, n, srcStart, fromData);
972 }
973 
974 //------------------------------------------------------------------------------
SetScalars(vtkDataArray * da)975 int vtkDataSetAttributes::SetScalars(vtkDataArray* da)
976 {
977   return this->SetAttribute(da, SCALARS);
978 }
979 
980 //------------------------------------------------------------------------------
SetActiveScalars(const char * name)981 int vtkDataSetAttributes::SetActiveScalars(const char* name)
982 {
983   return this->SetActiveAttribute(name, SCALARS);
984 }
985 
986 //------------------------------------------------------------------------------
SetActiveAttribute(const char * name,int attributeType)987 int vtkDataSetAttributes::SetActiveAttribute(const char* name, int attributeType)
988 {
989   int index;
990   this->GetAbstractArray(name, index);
991   return this->SetActiveAttribute(index, attributeType);
992 }
993 
994 //------------------------------------------------------------------------------
GetScalars()995 vtkDataArray* vtkDataSetAttributes::GetScalars()
996 {
997   return this->GetAttribute(SCALARS);
998 }
999 
1000 //------------------------------------------------------------------------------
SetVectors(vtkDataArray * da)1001 int vtkDataSetAttributes::SetVectors(vtkDataArray* da)
1002 {
1003   return this->SetAttribute(da, VECTORS);
1004 }
1005 
1006 //------------------------------------------------------------------------------
SetActiveVectors(const char * name)1007 int vtkDataSetAttributes::SetActiveVectors(const char* name)
1008 {
1009   return this->SetActiveAttribute(name, VECTORS);
1010 }
1011 
1012 //------------------------------------------------------------------------------
GetVectors()1013 vtkDataArray* vtkDataSetAttributes::GetVectors()
1014 {
1015   return this->GetAttribute(VECTORS);
1016 }
1017 
1018 //------------------------------------------------------------------------------
SetNormals(vtkDataArray * da)1019 int vtkDataSetAttributes::SetNormals(vtkDataArray* da)
1020 {
1021   return this->SetAttribute(da, NORMALS);
1022 }
1023 
1024 //------------------------------------------------------------------------------
SetActiveNormals(const char * name)1025 int vtkDataSetAttributes::SetActiveNormals(const char* name)
1026 {
1027   return this->SetActiveAttribute(name, NORMALS);
1028 }
1029 
1030 //------------------------------------------------------------------------------
GetNormals()1031 vtkDataArray* vtkDataSetAttributes::GetNormals()
1032 {
1033   return this->GetAttribute(NORMALS);
1034 }
1035 
1036 //------------------------------------------------------------------------------
SetTangents(vtkDataArray * da)1037 int vtkDataSetAttributes::SetTangents(vtkDataArray* da)
1038 {
1039   return this->SetAttribute(da, TANGENTS);
1040 }
1041 
1042 //------------------------------------------------------------------------------
SetActiveTangents(const char * name)1043 int vtkDataSetAttributes::SetActiveTangents(const char* name)
1044 {
1045   return this->SetActiveAttribute(name, TANGENTS);
1046 }
1047 
1048 //------------------------------------------------------------------------------
GetTangents()1049 vtkDataArray* vtkDataSetAttributes::GetTangents()
1050 {
1051   return this->GetAttribute(TANGENTS);
1052 }
1053 
1054 //------------------------------------------------------------------------------
SetTCoords(vtkDataArray * da)1055 int vtkDataSetAttributes::SetTCoords(vtkDataArray* da)
1056 {
1057   return this->SetAttribute(da, TCOORDS);
1058 }
1059 
1060 //------------------------------------------------------------------------------
SetActiveTCoords(const char * name)1061 int vtkDataSetAttributes::SetActiveTCoords(const char* name)
1062 {
1063   return this->SetActiveAttribute(name, TCOORDS);
1064 }
1065 //------------------------------------------------------------------------------
GetTCoords()1066 vtkDataArray* vtkDataSetAttributes::GetTCoords()
1067 {
1068   return this->GetAttribute(TCOORDS);
1069 }
1070 
1071 //------------------------------------------------------------------------------
SetTensors(vtkDataArray * da)1072 int vtkDataSetAttributes::SetTensors(vtkDataArray* da)
1073 {
1074   return this->SetAttribute(da, TENSORS);
1075 }
1076 
1077 //------------------------------------------------------------------------------
SetActiveTensors(const char * name)1078 int vtkDataSetAttributes::SetActiveTensors(const char* name)
1079 {
1080   return this->SetActiveAttribute(name, TENSORS);
1081 }
1082 
1083 //------------------------------------------------------------------------------
GetTensors()1084 vtkDataArray* vtkDataSetAttributes::GetTensors()
1085 {
1086   return this->GetAttribute(TENSORS);
1087 }
1088 
1089 //------------------------------------------------------------------------------
SetGlobalIds(vtkDataArray * da)1090 int vtkDataSetAttributes::SetGlobalIds(vtkDataArray* da)
1091 {
1092   return this->SetAttribute(da, GLOBALIDS);
1093 }
1094 
1095 //------------------------------------------------------------------------------
SetActiveGlobalIds(const char * name)1096 int vtkDataSetAttributes::SetActiveGlobalIds(const char* name)
1097 {
1098   return this->SetActiveAttribute(name, GLOBALIDS);
1099 }
1100 
1101 //------------------------------------------------------------------------------
GetGlobalIds()1102 vtkDataArray* vtkDataSetAttributes::GetGlobalIds()
1103 {
1104   return this->GetAttribute(GLOBALIDS);
1105 }
1106 
1107 //------------------------------------------------------------------------------
SetPedigreeIds(vtkAbstractArray * aa)1108 int vtkDataSetAttributes::SetPedigreeIds(vtkAbstractArray* aa)
1109 {
1110   return this->SetAttribute(aa, PEDIGREEIDS);
1111 }
1112 
1113 //------------------------------------------------------------------------------
SetActivePedigreeIds(const char * name)1114 int vtkDataSetAttributes::SetActivePedigreeIds(const char* name)
1115 {
1116   return this->SetActiveAttribute(name, PEDIGREEIDS);
1117 }
1118 
1119 //------------------------------------------------------------------------------
GetPedigreeIds()1120 vtkAbstractArray* vtkDataSetAttributes::GetPedigreeIds()
1121 {
1122   return this->GetAbstractAttribute(PEDIGREEIDS);
1123 }
1124 
1125 //------------------------------------------------------------------------------
SetRationalWeights(vtkDataArray * da)1126 int vtkDataSetAttributes::SetRationalWeights(vtkDataArray* da)
1127 {
1128   return this->SetAttribute(da, RATIONALWEIGHTS);
1129 }
1130 
1131 //------------------------------------------------------------------------------
SetActiveRationalWeights(const char * name)1132 int vtkDataSetAttributes::SetActiveRationalWeights(const char* name)
1133 {
1134   return this->SetActiveAttribute(name, RATIONALWEIGHTS);
1135 }
1136 
1137 //------------------------------------------------------------------------------
GetRationalWeights()1138 vtkDataArray* vtkDataSetAttributes::GetRationalWeights()
1139 {
1140   return this->GetAttribute(RATIONALWEIGHTS);
1141 }
1142 
1143 //------------------------------------------------------------------------------
SetHigherOrderDegrees(vtkDataArray * da)1144 int vtkDataSetAttributes::SetHigherOrderDegrees(vtkDataArray* da)
1145 {
1146   return this->SetAttribute(da, HIGHERORDERDEGREES);
1147 }
1148 
1149 //------------------------------------------------------------------------------
SetActiveHigherOrderDegrees(const char * name)1150 int vtkDataSetAttributes::SetActiveHigherOrderDegrees(const char* name)
1151 {
1152   return this->SetActiveAttribute(name, HIGHERORDERDEGREES);
1153 }
1154 
1155 //------------------------------------------------------------------------------
GetHigherOrderDegrees()1156 vtkDataArray* vtkDataSetAttributes::GetHigherOrderDegrees()
1157 {
1158   return this->GetAttribute(HIGHERORDERDEGREES);
1159 }
1160 
1161 //------------------------------------------------------------------------------
GetScalars(const char * name)1162 vtkDataArray* vtkDataSetAttributes::GetScalars(const char* name)
1163 {
1164   if (name == nullptr || name[0] == '\0')
1165   {
1166     return this->GetScalars();
1167   }
1168   return this->GetArray(name);
1169 }
1170 
1171 //------------------------------------------------------------------------------
GetVectors(const char * name)1172 vtkDataArray* vtkDataSetAttributes::GetVectors(const char* name)
1173 {
1174   if (name == nullptr || name[0] == '\0')
1175   {
1176     return this->GetVectors();
1177   }
1178   return this->GetArray(name);
1179 }
1180 
1181 //------------------------------------------------------------------------------
GetNormals(const char * name)1182 vtkDataArray* vtkDataSetAttributes::GetNormals(const char* name)
1183 {
1184   if (name == nullptr || name[0] == '\0')
1185   {
1186     return this->GetNormals();
1187   }
1188   return this->GetArray(name);
1189 }
1190 
1191 //------------------------------------------------------------------------------
GetTangents(const char * name)1192 vtkDataArray* vtkDataSetAttributes::GetTangents(const char* name)
1193 {
1194   if (name == nullptr || name[0] == '\0')
1195   {
1196     return this->GetTangents();
1197   }
1198   return this->GetArray(name);
1199 }
1200 
1201 //------------------------------------------------------------------------------
GetTCoords(const char * name)1202 vtkDataArray* vtkDataSetAttributes::GetTCoords(const char* name)
1203 {
1204   if (name == nullptr || name[0] == '\0')
1205   {
1206     return this->GetTCoords();
1207   }
1208   return this->GetArray(name);
1209 }
1210 
1211 //------------------------------------------------------------------------------
GetTensors(const char * name)1212 vtkDataArray* vtkDataSetAttributes::GetTensors(const char* name)
1213 {
1214   if (name == nullptr || name[0] == '\0')
1215   {
1216     return this->GetTensors();
1217   }
1218   return this->GetArray(name);
1219 }
1220 
1221 //------------------------------------------------------------------------------
GetGlobalIds(const char * name)1222 vtkDataArray* vtkDataSetAttributes::GetGlobalIds(const char* name)
1223 {
1224   if (name == nullptr || name[0] == '\0')
1225   {
1226     return this->GetGlobalIds();
1227   }
1228   return this->GetArray(name);
1229 }
1230 
1231 //------------------------------------------------------------------------------
GetPedigreeIds(const char * name)1232 vtkAbstractArray* vtkDataSetAttributes::GetPedigreeIds(const char* name)
1233 {
1234   if (name == nullptr || name[0] == '\0')
1235   {
1236     return this->GetPedigreeIds();
1237   }
1238   return this->GetAbstractArray(name);
1239 }
1240 
1241 //------------------------------------------------------------------------------
GetRationalWeights(const char * name)1242 vtkDataArray* vtkDataSetAttributes::GetRationalWeights(const char* name)
1243 {
1244   if (name == nullptr || name[0] == '\0')
1245   {
1246     return this->GetRationalWeights();
1247   }
1248   return this->GetArray(name);
1249 }
1250 
1251 //------------------------------------------------------------------------------
GetHigherOrderDegrees(const char * name)1252 vtkDataArray* vtkDataSetAttributes::GetHigherOrderDegrees(const char* name)
1253 {
1254   if (name == nullptr || name[0] == '\0')
1255   {
1256     return this->GetHigherOrderDegrees();
1257   }
1258   return this->GetArray(name);
1259 }
1260 
1261 //------------------------------------------------------------------------------
SetActiveAttribute(int index,int attributeType)1262 int vtkDataSetAttributes::SetActiveAttribute(int index, int attributeType)
1263 {
1264   if ((index >= 0) && (index < this->GetNumberOfArrays()))
1265   {
1266     if (attributeType != PEDIGREEIDS)
1267     {
1268       vtkDataArray* darray = vtkArrayDownCast<vtkDataArray>(this->Data[index]);
1269       if (!darray)
1270       {
1271         vtkWarningMacro("Can not set attribute "
1272           << vtkDataSetAttributes::AttributeNames[attributeType]
1273           << ". Only vtkDataArray subclasses can be set as active attributes.");
1274         return -1;
1275       }
1276       if (!vtkDataSetAttributes::CheckNumberOfComponents(darray, attributeType))
1277       {
1278         vtkWarningMacro("Can not set attribute "
1279           << vtkDataSetAttributes::AttributeNames[attributeType]
1280           << ". Incorrect number of components.");
1281         return -1;
1282       }
1283     }
1284 
1285     this->AttributeIndices[attributeType] = index;
1286     this->Modified();
1287     return index;
1288   }
1289   else if (index == -1)
1290   {
1291     this->AttributeIndices[attributeType] = index;
1292     this->Modified();
1293   }
1294 
1295   return -1;
1296 }
1297 
1298 //------------------------------------------------------------------------------
1299 const int
1300   vtkDataSetAttributes ::NumberOfAttributeComponents[vtkDataSetAttributes::NUM_ATTRIBUTES] = { 0, 3,
1301     3, 3, 9, 1, 1, 1, 3, 1, 3 };
1302 
1303 //------------------------------------------------------------------------------
1304 // Scalars set to NOLIMIT
1305 const int vtkDataSetAttributes ::AttributeLimits[vtkDataSetAttributes::NUM_ATTRIBUTES] = { NOLIMIT,
1306   EXACT, EXACT, MAX, EXACT, EXACT, EXACT, EXACT, EXACT, EXACT, EXACT };
1307 
1308 //------------------------------------------------------------------------------
CheckNumberOfComponents(vtkAbstractArray * aa,int attributeType)1309 int vtkDataSetAttributes::CheckNumberOfComponents(vtkAbstractArray* aa, int attributeType)
1310 {
1311   int numComp = aa->GetNumberOfComponents();
1312 
1313   if (vtkDataSetAttributes::AttributeLimits[attributeType] == MAX)
1314   {
1315     if (numComp > vtkDataSetAttributes::NumberOfAttributeComponents[attributeType])
1316     {
1317       return 0;
1318     }
1319     else
1320     {
1321       return 1;
1322     }
1323   }
1324   else if (vtkDataSetAttributes::AttributeLimits[attributeType] == EXACT)
1325   {
1326     if (numComp == vtkDataSetAttributes::NumberOfAttributeComponents[attributeType] ||
1327       (numComp == 6 && attributeType == TENSORS)) // TENSORS6 support
1328     {
1329       return 1;
1330     }
1331     else
1332     {
1333       return 0;
1334     }
1335   }
1336   else if (vtkDataSetAttributes::AttributeLimits[attributeType] == NOLIMIT)
1337   {
1338     return 1;
1339   }
1340   else
1341   {
1342     return 0;
1343   }
1344 }
1345 
1346 //------------------------------------------------------------------------------
GetAttribute(int attributeType)1347 vtkDataArray* vtkDataSetAttributes::GetAttribute(int attributeType)
1348 {
1349   int index = this->AttributeIndices[attributeType];
1350   if (index == -1)
1351   {
1352     return nullptr;
1353   }
1354   else
1355   {
1356     return vtkArrayDownCast<vtkDataArray>(this->Data[index]);
1357   }
1358 }
1359 
1360 //------------------------------------------------------------------------------
GetAbstractAttribute(int attributeType)1361 vtkAbstractArray* vtkDataSetAttributes::GetAbstractAttribute(int attributeType)
1362 {
1363   int index = this->AttributeIndices[attributeType];
1364   if (index == -1)
1365   {
1366     return nullptr;
1367   }
1368   else
1369   {
1370     return this->Data[index];
1371   }
1372 }
1373 
1374 //------------------------------------------------------------------------------
1375 // This method lets the user add an array and make it the current
1376 // scalars, vectors etc... (this is determined by the attribute type
1377 // which is an enum defined vtkDataSetAttributes)
SetAttribute(vtkAbstractArray * aa,int attributeType)1378 int vtkDataSetAttributes::SetAttribute(vtkAbstractArray* aa, int attributeType)
1379 {
1380   if (aa && attributeType != PEDIGREEIDS && !vtkArrayDownCast<vtkDataArray>(aa))
1381   {
1382     vtkWarningMacro("Can not set attribute "
1383       << vtkDataSetAttributes::AttributeNames[attributeType]
1384       << ". This attribute must be a subclass of vtkDataArray.");
1385     return -1;
1386   }
1387   if (aa && !this->CheckNumberOfComponents(aa, attributeType))
1388   {
1389     vtkWarningMacro("Can not set attribute " << vtkDataSetAttributes::AttributeNames[attributeType]
1390                                              << ". Incorrect number of components.");
1391     return -1;
1392   }
1393 
1394   int currentAttribute = this->AttributeIndices[attributeType];
1395 
1396   // If there is an existing attribute, replace it
1397   if ((currentAttribute >= 0) && (currentAttribute < this->GetNumberOfArrays()))
1398   {
1399     if (this->GetAbstractArray(currentAttribute) == aa)
1400     {
1401       return currentAttribute;
1402     }
1403     this->RemoveArray(currentAttribute);
1404   }
1405 
1406   if (aa)
1407   {
1408     // Add the array
1409     currentAttribute = this->AddArray(aa);
1410     this->AttributeIndices[attributeType] = currentAttribute;
1411   }
1412   else
1413   {
1414     this->AttributeIndices[attributeType] = -1; // attribute of this type doesn't exist
1415   }
1416   this->Modified();
1417   return this->AttributeIndices[attributeType];
1418 }
1419 
1420 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1421 void vtkDataSetAttributes::PrintSelf(ostream& os, vtkIndent indent)
1422 {
1423   this->Superclass::PrintSelf(os, indent);
1424 
1425   // Print the copy flags
1426   int i;
1427   os << indent << "Copy Tuple Flags: ( ";
1428   for (i = 0; i < NUM_ATTRIBUTES; i++)
1429   {
1430     os << this->CopyAttributeFlags[COPYTUPLE][i] << " ";
1431   }
1432   os << ")" << endl;
1433   os << indent << "Interpolate Flags: ( ";
1434   for (i = 0; i < NUM_ATTRIBUTES; i++)
1435   {
1436     os << this->CopyAttributeFlags[INTERPOLATE][i] << " ";
1437   }
1438   os << ")" << endl;
1439   os << indent << "Pass Through Flags: ( ";
1440   for (i = 0; i < NUM_ATTRIBUTES; i++)
1441   {
1442     os << this->CopyAttributeFlags[PASSDATA][i] << " ";
1443   }
1444   os << ")" << endl;
1445 
1446   // Now print the various attributes
1447   vtkAbstractArray* aa;
1448   int attributeType;
1449   for (attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++)
1450   {
1451     os << indent << vtkDataSetAttributes::AttributeNames[attributeType] << ": ";
1452     if ((aa = this->GetAbstractAttribute(attributeType)))
1453     {
1454       os << endl;
1455       aa->PrintSelf(os, indent.GetNextIndent());
1456     }
1457     else
1458     {
1459       os << "(none)" << endl;
1460     }
1461   }
1462 }
1463 
1464 //------------------------------------------------------------------------------
GetAttributeIndices(int * indexArray)1465 void vtkDataSetAttributes::GetAttributeIndices(int* indexArray)
1466 {
1467   int i;
1468   for (i = 0; i < NUM_ATTRIBUTES; i++)
1469   {
1470     indexArray[i] = this->AttributeIndices[i];
1471   }
1472 }
1473 
1474 //------------------------------------------------------------------------------
IsArrayAnAttribute(int idx)1475 int vtkDataSetAttributes::IsArrayAnAttribute(int idx)
1476 {
1477   int i;
1478   for (i = 0; i < NUM_ATTRIBUTES; i++)
1479   {
1480     if (idx == this->AttributeIndices[i])
1481     {
1482       return i;
1483     }
1484   }
1485   return -1;
1486 }
1487 
1488 //------------------------------------------------------------------------------
SetCopyAttribute(int index,int value,int ctype)1489 void vtkDataSetAttributes::SetCopyAttribute(int index, int value, int ctype)
1490 {
1491   if (index < 0 || ctype < 0 || index >= vtkDataSetAttributes::NUM_ATTRIBUTES ||
1492     ctype > vtkDataSetAttributes::ALLCOPY)
1493   {
1494     vtkErrorMacro("Cannot set copy attribute for attribute type "
1495       << index << " and copy operation " << ctype << ". These values are out of range.");
1496     return;
1497   }
1498 
1499   if (ctype == vtkDataSetAttributes::ALLCOPY)
1500   {
1501     int t;
1502     for (t = COPYTUPLE; t < vtkDataSetAttributes::ALLCOPY; t++)
1503     {
1504       if (this->CopyAttributeFlags[t][index] != value)
1505       {
1506         this->CopyAttributeFlags[t][index] = value;
1507         this->Modified();
1508       }
1509     }
1510   }
1511   else
1512   {
1513     if (this->CopyAttributeFlags[ctype][index] != value)
1514     {
1515       this->CopyAttributeFlags[ctype][index] = value;
1516       this->Modified();
1517     }
1518   }
1519 }
1520 
1521 //------------------------------------------------------------------------------
GetCopyAttribute(int index,int ctype)1522 int vtkDataSetAttributes::GetCopyAttribute(int index, int ctype)
1523 {
1524   if (index < 0 || ctype < 0 || index >= vtkDataSetAttributes::NUM_ATTRIBUTES ||
1525     ctype > vtkDataSetAttributes::ALLCOPY)
1526   {
1527     vtkWarningMacro("Cannot get copy attribute for attribute type "
1528       << index << " and copy operation " << ctype << ". These values are out of range.");
1529     return -1;
1530   }
1531   else if (ctype == vtkDataSetAttributes::ALLCOPY)
1532   {
1533     return (this->CopyAttributeFlags[COPYTUPLE][index] &&
1534       this->CopyAttributeFlags[INTERPOLATE][index] && this->CopyAttributeFlags[PASSDATA][index]);
1535   }
1536   else
1537   {
1538     return this->CopyAttributeFlags[ctype][index];
1539   }
1540 }
1541 
1542 //------------------------------------------------------------------------------
SetCopyScalars(vtkTypeBool i,int ctype)1543 void vtkDataSetAttributes::SetCopyScalars(vtkTypeBool i, int ctype)
1544 {
1545   this->SetCopyAttribute(SCALARS, i, ctype);
1546 }
1547 
1548 //------------------------------------------------------------------------------
GetCopyScalars(int ctype)1549 vtkTypeBool vtkDataSetAttributes::GetCopyScalars(int ctype)
1550 {
1551   return this->GetCopyAttribute(SCALARS, ctype);
1552 }
1553 
1554 //------------------------------------------------------------------------------
SetCopyVectors(vtkTypeBool i,int ctype)1555 void vtkDataSetAttributes::SetCopyVectors(vtkTypeBool i, int ctype)
1556 {
1557   this->SetCopyAttribute(VECTORS, i, ctype);
1558 }
1559 
1560 //------------------------------------------------------------------------------
GetCopyVectors(int ctype)1561 vtkTypeBool vtkDataSetAttributes::GetCopyVectors(int ctype)
1562 {
1563   return this->GetCopyAttribute(VECTORS, ctype);
1564 }
1565 
1566 //------------------------------------------------------------------------------
SetCopyNormals(vtkTypeBool i,int ctype)1567 void vtkDataSetAttributes::SetCopyNormals(vtkTypeBool i, int ctype)
1568 {
1569   this->SetCopyAttribute(NORMALS, i, ctype);
1570 }
1571 
1572 //------------------------------------------------------------------------------
GetCopyNormals(int ctype)1573 vtkTypeBool vtkDataSetAttributes::GetCopyNormals(int ctype)
1574 {
1575   return this->GetCopyAttribute(NORMALS, ctype);
1576 }
1577 
1578 //------------------------------------------------------------------------------
SetCopyTangents(vtkTypeBool i,int ctype)1579 void vtkDataSetAttributes::SetCopyTangents(vtkTypeBool i, int ctype)
1580 {
1581   this->SetCopyAttribute(TANGENTS, i, ctype);
1582 }
1583 
1584 //------------------------------------------------------------------------------
GetCopyTangents(int ctype)1585 vtkTypeBool vtkDataSetAttributes::GetCopyTangents(int ctype)
1586 {
1587   return this->GetCopyAttribute(TANGENTS, ctype);
1588 }
1589 
1590 //------------------------------------------------------------------------------
SetCopyTCoords(vtkTypeBool i,int ctype)1591 void vtkDataSetAttributes::SetCopyTCoords(vtkTypeBool i, int ctype)
1592 {
1593   this->SetCopyAttribute(TCOORDS, i, ctype);
1594 }
1595 
1596 //------------------------------------------------------------------------------
GetCopyTCoords(int ctype)1597 vtkTypeBool vtkDataSetAttributes::GetCopyTCoords(int ctype)
1598 {
1599   return this->GetCopyAttribute(TCOORDS, ctype);
1600 }
1601 
1602 //------------------------------------------------------------------------------
SetCopyTensors(vtkTypeBool i,int ctype)1603 void vtkDataSetAttributes::SetCopyTensors(vtkTypeBool i, int ctype)
1604 {
1605   this->SetCopyAttribute(TENSORS, i, ctype);
1606 }
1607 //------------------------------------------------------------------------------
GetCopyTensors(int ctype)1608 vtkTypeBool vtkDataSetAttributes::GetCopyTensors(int ctype)
1609 {
1610   return this->GetCopyAttribute(TENSORS, ctype);
1611 }
1612 
1613 //------------------------------------------------------------------------------
SetCopyGlobalIds(vtkTypeBool i,int ctype)1614 void vtkDataSetAttributes::SetCopyGlobalIds(vtkTypeBool i, int ctype)
1615 {
1616   this->SetCopyAttribute(GLOBALIDS, i, ctype);
1617 }
1618 
1619 //------------------------------------------------------------------------------
GetCopyGlobalIds(int ctype)1620 vtkTypeBool vtkDataSetAttributes::GetCopyGlobalIds(int ctype)
1621 {
1622   return this->GetCopyAttribute(GLOBALIDS, ctype);
1623 }
1624 
1625 //------------------------------------------------------------------------------
SetCopyPedigreeIds(vtkTypeBool i,int ctype)1626 void vtkDataSetAttributes::SetCopyPedigreeIds(vtkTypeBool i, int ctype)
1627 {
1628   this->SetCopyAttribute(PEDIGREEIDS, i, ctype);
1629 }
1630 
1631 //------------------------------------------------------------------------------
GetCopyPedigreeIds(int ctype)1632 vtkTypeBool vtkDataSetAttributes::GetCopyPedigreeIds(int ctype)
1633 {
1634   return this->GetCopyAttribute(PEDIGREEIDS, ctype);
1635 }
1636 
1637 //------------------------------------------------------------------------------
SetCopyRationalWeights(vtkTypeBool i,int ctype)1638 void vtkDataSetAttributes::SetCopyRationalWeights(vtkTypeBool i, int ctype)
1639 {
1640   this->SetCopyAttribute(RATIONALWEIGHTS, i, ctype);
1641 }
1642 
1643 //------------------------------------------------------------------------------
GetCopyRationalWeights(int ctype)1644 vtkTypeBool vtkDataSetAttributes::GetCopyRationalWeights(int ctype)
1645 {
1646   return this->GetCopyAttribute(RATIONALWEIGHTS, ctype);
1647 }
1648 
1649 //------------------------------------------------------------------------------
SetCopyHigherOrderDegrees(vtkTypeBool i,int ctype)1650 void vtkDataSetAttributes::SetCopyHigherOrderDegrees(vtkTypeBool i, int ctype)
1651 {
1652   this->SetCopyAttribute(HIGHERORDERDEGREES, i, ctype);
1653 }
1654 
1655 //------------------------------------------------------------------------------
GetCopyHigherOrderDegrees(int ctype)1656 vtkTypeBool vtkDataSetAttributes::GetCopyHigherOrderDegrees(int ctype)
1657 {
1658   return this->GetCopyAttribute(HIGHERORDERDEGREES, ctype);
1659 }
1660 
1661 //------------------------------------------------------------------------------
CopyAllocate(vtkDataSetAttributes::FieldList & list,vtkIdType sze,vtkIdType ext)1662 void vtkDataSetAttributes::CopyAllocate(
1663   vtkDataSetAttributes::FieldList& list, vtkIdType sze, vtkIdType ext)
1664 {
1665   list.CopyAllocate(this, COPYTUPLE, sze, ext);
1666 }
1667 
1668 //------------------------------------------------------------------------------
InterpolateAllocate(vtkDataSetAttributes::FieldList & list,vtkIdType sze,vtkIdType ext)1669 void vtkDataSetAttributes::InterpolateAllocate(
1670   vtkDataSetAttributes::FieldList& list, vtkIdType sze, vtkIdType ext)
1671 {
1672   list.CopyAllocate(this, INTERPOLATE, sze, ext);
1673 }
1674 
1675 //------------------------------------------------------------------------------
1676 // Description:
1677 // A special form of CopyData() to be used with FieldLists. Use it when you are
1678 // copying data from a set of vtkDataSetAttributes. Make sure that you have
1679 // called the special form of CopyAllocate that accepts FieldLists.
CopyData(vtkDataSetAttributes::FieldList & list,vtkDataSetAttributes * fromDSA,int idx,vtkIdType fromId,vtkIdType toId)1680 void vtkDataSetAttributes::CopyData(vtkDataSetAttributes::FieldList& list,
1681   vtkDataSetAttributes* fromDSA, int idx, vtkIdType fromId, vtkIdType toId)
1682 {
1683   list.CopyData(idx, fromDSA, fromId, this, toId);
1684 }
1685 
1686 //------------------------------------------------------------------------------
1687 // Description:
1688 // A special form of CopyData() to be used with FieldLists. Use it when you are
1689 // copying data from a set of vtkDataSetAttributes. Make sure that you have
1690 // called the special form of CopyAllocate that accepts FieldLists.
CopyData(vtkDataSetAttributes::FieldList & list,vtkDataSetAttributes * fromDSA,int idx,vtkIdType dstStart,vtkIdType n,vtkIdType srcStart)1691 void vtkDataSetAttributes::CopyData(vtkDataSetAttributes::FieldList& list,
1692   vtkDataSetAttributes* fromDSA, int idx, vtkIdType dstStart, vtkIdType n, vtkIdType srcStart)
1693 {
1694   list.CopyData(idx, fromDSA, srcStart, n, this, dstStart);
1695 }
1696 
1697 //------------------------------------------------------------------------------
1698 // Interpolate data from points and interpolation weights. Make sure that the
1699 // method InterpolateAllocate() has been invoked before using this method.
InterpolatePoint(vtkDataSetAttributes::FieldList & list,vtkDataSetAttributes * fromPd,int idx,vtkIdType toId,vtkIdList * ptIds,double * weights)1700 void vtkDataSetAttributes::InterpolatePoint(vtkDataSetAttributes::FieldList& list,
1701   vtkDataSetAttributes* fromPd, int idx, vtkIdType toId, vtkIdList* ptIds, double* weights)
1702 {
1703   list.InterpolatePoint(idx, fromPd, ptIds, weights, this, toId);
1704 }
1705 
1706 //------------------------------------------------------------------------------
GetAttributeTypeAsString(int attributeType)1707 const char* vtkDataSetAttributes::GetAttributeTypeAsString(int attributeType)
1708 {
1709   if (attributeType < 0 || attributeType >= NUM_ATTRIBUTES)
1710   {
1711     vtkGenericWarningMacro("Bad attribute type: " << attributeType << ".");
1712     return nullptr;
1713   }
1714   return vtkDataSetAttributes::AttributeNames[attributeType];
1715 }
1716 
1717 //------------------------------------------------------------------------------
GetLongAttributeTypeAsString(int attributeType)1718 const char* vtkDataSetAttributes::GetLongAttributeTypeAsString(int attributeType)
1719 {
1720   if (attributeType < 0 || attributeType >= NUM_ATTRIBUTES)
1721   {
1722     vtkGenericWarningMacro("Bad attribute type: " << attributeType << ".");
1723     return nullptr;
1724   }
1725   return vtkDataSetAttributes::LongAttributeNames[attributeType];
1726 }
1727