1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkAOSDataArrayTemplate.h 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 /** 16 * @class vtkAOSDataArrayTemplate 17 * @brief Array-Of-Structs implementation of 18 * vtkGenericDataArray. 19 * 20 * 21 * vtkGenericDataArray specialization that stores data array in the traditional 22 * VTK memory layout where a 3 component is stored in contiguous memory as 23 * \c A1A2A3B1B2B3C1C2C3 ... where A,B,C,... are tuples. 24 * 25 * This replaces vtkDataArrayTemplate. 26 * 27 * @sa 28 * vtkGenericDataArray vtkSOADataArrayTemplate 29 */ 30 31 #ifndef vtkAOSDataArrayTemplate_h 32 #define vtkAOSDataArrayTemplate_h 33 34 #include "vtkCommonCoreModule.h" // For export macro 35 #include "vtkGenericDataArray.h" 36 #include "vtkBuffer.h" // For storage buffer. 37 38 // The export macro below makes no sense, but is necessary for older compilers 39 // when we export instantiations of this class from vtkCommonCore. 40 template <class ValueTypeT> 41 class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate : 42 public vtkGenericDataArray<vtkAOSDataArrayTemplate<ValueTypeT>, ValueTypeT> 43 { 44 typedef vtkGenericDataArray<vtkAOSDataArrayTemplate<ValueTypeT>, ValueTypeT> 45 GenericDataArrayType; 46 public: 47 typedef vtkAOSDataArrayTemplate<ValueTypeT> SelfType; 48 vtkTemplateTypeMacro(SelfType, GenericDataArrayType) 49 typedef typename Superclass::ValueType ValueType; 50 51 enum DeleteMethod 52 { 53 VTK_DATA_ARRAY_FREE=vtkAbstractArray::VTK_DATA_ARRAY_FREE, 54 VTK_DATA_ARRAY_DELETE=vtkAbstractArray::VTK_DATA_ARRAY_DELETE, 55 VTK_DATA_ARRAY_ALIGNED_FREE=vtkAbstractArray::VTK_DATA_ARRAY_ALIGNED_FREE, 56 VTK_DATA_ARRAY_USER_DEFINED=vtkAbstractArray::VTK_DATA_ARRAY_USER_DEFINED 57 }; 58 59 static vtkAOSDataArrayTemplate* New(); 60 61 /** 62 * Get the value at @a valueIdx. @a valueIdx assumes AOS ordering. 63 */ GetValue(vtkIdType valueIdx)64 ValueType GetValue(vtkIdType valueIdx) const 65 VTK_EXPECTS(0 <= valueIdx && valueIdx < GetNumberOfValues()) 66 { 67 return this->Buffer->GetBuffer()[valueIdx]; 68 } 69 70 /** 71 * Set the value at @a valueIdx to @a value. @a valueIdx assumes AOS ordering. 72 */ SetValue(vtkIdType valueIdx,ValueType value)73 void SetValue(vtkIdType valueIdx, ValueType value) 74 VTK_EXPECTS(0 <= valueIdx && valueIdx < GetNumberOfValues()) 75 { 76 this->Buffer->GetBuffer()[valueIdx] = value; 77 } 78 79 //@{ 80 /** 81 * Copy the tuple at @a tupleIdx into @a tuple. 82 */ GetTypedTuple(vtkIdType tupleIdx,ValueType * tuple)83 void GetTypedTuple(vtkIdType tupleIdx, ValueType* tuple) const 84 VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples()) 85 { 86 const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents; 87 std::copy(this->Buffer->GetBuffer() + valueIdx, 88 this->Buffer->GetBuffer() + valueIdx + this->NumberOfComponents, 89 tuple); 90 } 91 //@} 92 93 //@{ 94 /** 95 * Set this array's tuple at @a tupleIdx to the values in @a tuple. 96 */ SetTypedTuple(vtkIdType tupleIdx,const ValueType * tuple)97 void SetTypedTuple(vtkIdType tupleIdx, const ValueType* tuple) 98 VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples()) 99 { 100 const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents; 101 std::copy(tuple, tuple + this->NumberOfComponents, 102 this->Buffer->GetBuffer() + valueIdx); 103 } 104 //@} 105 106 /** 107 * Get component @a comp of the tuple at @a tupleIdx. 108 */ GetTypedComponent(vtkIdType tupleIdx,int comp)109 ValueType GetTypedComponent(vtkIdType tupleIdx, int comp) const 110 VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples()) 111 VTK_EXPECTS(0 <= comp && comp < GetNumberOfComponents()) 112 { 113 return this->Buffer->GetBuffer()[this->NumberOfComponents*tupleIdx + comp]; 114 } 115 116 //@{ 117 /** 118 * Set component @a comp of the tuple at @a tupleIdx to @a value. 119 */ SetTypedComponent(vtkIdType tupleIdx,int comp,ValueType value)120 void SetTypedComponent(vtkIdType tupleIdx, int comp, ValueType value) 121 VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples()) 122 VTK_EXPECTS(0 <= comp && comp < GetNumberOfComponents()) 123 { 124 const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents + comp; 125 this->SetValue(valueIdx, value); 126 } 127 //@} 128 129 //@{ 130 /** 131 * Set component @a comp of all tuples to @a value. 132 */ 133 void FillTypedComponent(int compIdx, ValueType value) override; 134 //@} 135 136 //@{ 137 /** 138 * Set all the values in array to @a value. 139 */ 140 void FillValue(ValueType value) override; 141 void Fill(double value) override; 142 //@} 143 144 //@{ 145 /** 146 * Get the address of a particular data index. Make sure data is allocated 147 * for the number of items requested. Set MaxId according to the number of 148 * data values requested. 149 */ 150 ValueType* WritePointer(vtkIdType valueIdx, vtkIdType numValues); 151 void* WriteVoidPointer(vtkIdType valueIdx, vtkIdType numValues) override; 152 //@} 153 154 //@{ 155 /** 156 * Get the address of a particular data index. Performs no checks 157 * to verify that the memory has been allocated etc. 158 * Use of this method is discouraged, as newer arrays require a deep-copy of 159 * the array data in order to return a suitable pointer. See vtkArrayDispatch 160 * for a safer alternative for fast data access. 161 */ 162 ValueType* GetPointer(vtkIdType valueIdx); 163 void* GetVoidPointer(vtkIdType valueIdx) override; 164 //@} 165 166 //@{ 167 /** 168 * This method lets the user specify data to be held by the array. The 169 * array argument is a pointer to the data. size is the size of the 170 * array supplied by the user (as number of values, not in bytes). 171 * Set save to 1 to prevent the class from 172 * deleting the array when it cleans up or reallocates memory. The class 173 * uses the actual array provided; it does not copy the data from the 174 * suppled array. If specified, the delete method determines how the data 175 * array will be deallocated. If the delete method is 176 * VTK_DATA_ARRAY_FREE, free() will be used. If the delete method is 177 * VTK_DATA_ARRAY_DELETE, delete[] will be used. If the delete method is 178 * VTK_DATA_ARRAY_ALIGNED_FREE _aligned_free() will be used on Windows, while 179 * free() will be used everywhere else. The default is FREE. 180 */ 181 void SetArray(VTK_ZEROCOPY ValueType* array, vtkIdType size, int save, 182 int deleteMethod); 183 void SetArray(VTK_ZEROCOPY ValueType* array, vtkIdType size, int save); 184 void SetVoidArray(void* array, vtkIdType size, int save) override; 185 void SetVoidArray(void* array, vtkIdType size, int save, 186 int deleteMethod) override; 187 //@} 188 189 /** 190 * This method allows the user to specify a custom free function to be 191 * called when the array is deallocated. Calling this method will implicitly 192 * mean that the given free function will be called when the class 193 * cleans up or reallocates memory. 194 **/ 195 void SetArrayFreeFunction(void (*callback)(void *)) override; 196 197 // Overridden for optimized implementations: 198 void SetTuple(vtkIdType tupleIdx, const float *tuple) override; 199 void SetTuple(vtkIdType tupleIdx, const double *tuple) override; 200 // MSVC doesn't like 'using' here (error C2487). Just forward instead: 201 // using Superclass::SetTuple; SetTuple(vtkIdType dstTupleIdx,vtkIdType srcTupleIdx,vtkAbstractArray * source)202 void SetTuple(vtkIdType dstTupleIdx, vtkIdType srcTupleIdx, 203 vtkAbstractArray *source) override 204 { this->Superclass::SetTuple(dstTupleIdx, srcTupleIdx, source); } 205 void InsertTuple(vtkIdType tupleIdx, const float *source) override; 206 void InsertTuple(vtkIdType tupleIdx, const double *source) override; 207 // MSVC doesn't like 'using' here (error C2487). Just forward instead: 208 // using Superclass::InsertTuple; InsertTuple(vtkIdType dstTupleIdx,vtkIdType srcTupleIdx,vtkAbstractArray * source)209 void InsertTuple(vtkIdType dstTupleIdx, vtkIdType srcTupleIdx, 210 vtkAbstractArray *source) override 211 { this->Superclass::InsertTuple(dstTupleIdx, srcTupleIdx, source); } 212 void InsertComponent(vtkIdType tupleIdx, int compIdx, 213 double value) override; 214 vtkIdType InsertNextTuple(const float *tuple) override; 215 vtkIdType InsertNextTuple(const double *tuple) override; 216 // MSVC doesn't like 'using' here (error C2487). Just forward instead: 217 // using Superclass::InsertNextTuple; InsertNextTuple(vtkIdType srcTupleIdx,vtkAbstractArray * source)218 vtkIdType InsertNextTuple(vtkIdType srcTupleIdx, 219 vtkAbstractArray *source) override 220 { return this->Superclass::InsertNextTuple(srcTupleIdx, source); } 221 void GetTuple(vtkIdType tupleIdx, double * tuple) override; 222 double *GetTuple(vtkIdType tupleIdx) override; 223 224 /** 225 * Tell the array explicitly that a single data element has 226 * changed. Like DataChanged(), then is only necessary when you 227 * modify the array contents without using the array's API. 228 * @note This is a legacy method from vtkDataArrayTemplate, and is only 229 * implemented for array-of-struct arrays. It currently just calls 230 * DataChanged() and does nothing clever. 231 * TODO this is only defined for AOS (vtkDataArrayTemplate leftover). 232 * Deprecate to favor DataChanged? 233 */ DataElementChanged(vtkIdType)234 void DataElementChanged(vtkIdType) { this->DataChanged(); } 235 236 /** 237 * Legacy support for array-of-structs value iteration. 238 * TODO Deprecate? 239 */ 240 typedef ValueType* Iterator; Begin()241 Iterator Begin() { return Iterator(this->GetVoidPointer(0)); } End()242 Iterator End() { return Iterator(this->GetVoidPointer(this->MaxId + 1)); } 243 244 //@{ 245 /** 246 * Perform a fast, safe cast from a vtkAbstractArray to a 247 * vtkAOSDataArrayTemplate. 248 * This method checks if source->GetArrayType() returns DataArray 249 * or a more derived type, and performs a static_cast to return 250 * source as a vtkDataArray pointer. Otherwise, nullptr is returned. 251 */ 252 static vtkAOSDataArrayTemplate<ValueType>* FastDownCast(vtkAbstractArray * source)253 FastDownCast(vtkAbstractArray *source) 254 { 255 if (source) 256 { 257 switch (source->GetArrayType()) 258 { 259 case vtkAbstractArray::AoSDataArrayTemplate: 260 if (vtkDataTypesCompare(source->GetDataType(), 261 vtkTypeTraits<ValueType>::VTK_TYPE_ID)) 262 { 263 return static_cast<vtkAOSDataArrayTemplate<ValueType>*>(source); 264 } 265 break; 266 } 267 } 268 return nullptr; 269 } 270 //@} 271 GetArrayType()272 int GetArrayType() override { return vtkAbstractArray::AoSDataArrayTemplate; } 273 VTK_NEWINSTANCE vtkArrayIterator *NewIterator() override; HasStandardMemoryLayout()274 bool HasStandardMemoryLayout() override { return true; } 275 void ShallowCopy(vtkDataArray *other) override; 276 277 // Reimplemented for efficiency: 278 void InsertTuples(vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, 279 vtkAbstractArray* source) override; 280 // MSVC doesn't like 'using' here (error C2487). Just forward instead: 281 // using Superclass::InsertTuples; InsertTuples(vtkIdList * dstIds,vtkIdList * srcIds,vtkAbstractArray * source)282 void InsertTuples(vtkIdList *dstIds, vtkIdList *srcIds, 283 vtkAbstractArray *source) override 284 { this->Superclass::InsertTuples(dstIds, srcIds, source); } 285 286 protected: 287 vtkAOSDataArrayTemplate(); 288 ~vtkAOSDataArrayTemplate() override; 289 290 /** 291 * Allocate space for numTuples. Old data is not preserved. If numTuples == 0, 292 * all data is freed. 293 */ 294 bool AllocateTuples(vtkIdType numTuples); 295 296 /** 297 * Allocate space for numTuples. Old data is preserved. If numTuples == 0, 298 * all data is freed. 299 */ 300 bool ReallocateTuples(vtkIdType numTuples); 301 302 vtkBuffer<ValueType> *Buffer; 303 304 private: 305 vtkAOSDataArrayTemplate(const vtkAOSDataArrayTemplate&) = delete; 306 void operator=(const vtkAOSDataArrayTemplate&) = delete; 307 308 friend class vtkGenericDataArray<vtkAOSDataArrayTemplate<ValueTypeT>, 309 ValueTypeT>; 310 311 }; 312 313 // Declare vtkArrayDownCast implementations for AoS containers: 314 vtkArrayDownCast_TemplateFastCastMacro(vtkAOSDataArrayTemplate) 315 316 // This macro is used by the subclasses to create dummy 317 // declarations for these functions such that the wrapper 318 // can see them. The wrappers ignore vtkAOSDataArrayTemplate. 319 #define vtkCreateWrappedArrayInterface(T) \ 320 int GetDataType() override;\ 321 void GetTypedTuple(vtkIdType i, T* tuple) \ 322 VTK_EXPECTS(0 <= i && i < GetNumberOfTuples()); \ 323 void SetTypedTuple(vtkIdType i, const T* tuple) \ 324 VTK_EXPECTS(0 <= i && i < GetNumberOfTuples()); \ 325 void InsertTypedTuple(vtkIdType i, const T* tuple) \ 326 VTK_EXPECTS(0 <= i); \ 327 vtkIdType InsertNextTypedTuple(const T* tuple); \ 328 T GetValue(vtkIdType id) \ 329 VTK_EXPECTS(0 <= id && id < GetNumberOfValues()); \ 330 void SetValue(vtkIdType id, T value) \ 331 VTK_EXPECTS(0 <= id && id < GetNumberOfValues()); \ 332 void SetNumberOfValues(vtkIdType number) override;\ 333 void InsertValue(vtkIdType id, T f) \ 334 VTK_EXPECTS(0 <= id); \ 335 vtkIdType InsertNextValue(T f); \ 336 T *GetValueRange(int comp) VTK_SIZEHINT(2); \ 337 T *GetValueRange() VTK_SIZEHINT(2); \ 338 T* WritePointer(vtkIdType id, vtkIdType number); \ 339 T* GetPointer(vtkIdType id); \ 340 void SetArray(VTK_ZEROCOPY T* array, vtkIdType size, int save); \ 341 void SetArray(VTK_ZEROCOPY T* array, vtkIdType size, int save, int deleteMethod) 342 343 #endif // header guard 344 345 // This portion must be OUTSIDE the include blockers. This is used to tell 346 // libraries other than vtkCommonCore that instantiations of 347 // vtkAOSDataArrayTemplate can be found externally. This prevents each library 348 // from instantiating these on their own. 349 #ifdef VTK_AOS_DATA_ARRAY_TEMPLATE_INSTANTIATING 350 #define VTK_AOS_DATA_ARRAY_TEMPLATE_INSTANTIATE(T) \ 351 template class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate< T > 352 #elif defined(VTK_USE_EXTERN_TEMPLATE) 353 #ifndef VTK_AOS_DATA_ARRAY_TEMPLATE_EXTERN 354 #define VTK_AOS_DATA_ARRAY_TEMPLATE_EXTERN 355 #ifdef _MSC_VER 356 #pragma warning (push) 357 // The following is needed when the vtkAOSDataArrayTemplate is declared 358 // dllexport and is used from another class in vtkCommonCore 359 #pragma warning (disable: 4910) // extern and dllexport incompatible 360 #endif 361 vtkExternTemplateMacro( 362 extern template class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate) 363 #ifdef _MSC_VER 364 #pragma warning (pop) 365 #endif 366 #endif // VTK_AOS_DATA_ARRAY_TEMPLATE_EXTERN 367 368 // The following clause is only for MSVC 369 #elif defined(_MSC_VER) && !defined(VTK_BUILD_SHARED_LIBS) 370 #pragma warning (push) 371 372 // C4091: 'extern ' : ignored on left of 'int' when no variable is declared 373 #pragma warning (disable: 4091) 374 375 // Compiler-specific extension warning. 376 #pragma warning (disable: 4231) 377 378 // We need to disable warning 4910 and do an extern dllexport 379 // anyway. When deriving vtkCharArray and other types from an 380 // instantiation of this template the compiler does an explicit 381 // instantiation of the base class. From outside the vtkCommon 382 // library we block this using an extern dllimport instantiation. 383 // For classes inside vtkCommon we should be able to just do an 384 // extern instantiation, but VS complains about missing 385 // definitions. We cannot do an extern dllimport inside vtkCommon 386 // since the symbols are local to the dll. An extern dllexport 387 // seems to be the only way to convince VS to do the right 388 // thing, so we just disable the warning. 389 #pragma warning (disable: 4910) // extern and dllexport incompatible 390 391 // Use an "extern explicit instantiation" to give the class a DLL 392 // interface. This is a compiler-specific extension. 393 vtkInstantiateTemplateMacro( 394 extern template class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate) 395 396 #pragma warning (pop) 397 398 #endif 399 400 // VTK-HeaderTest-Exclude: vtkAOSDataArrayTemplate.h 401