Compare vtk data types and basic data types

空扰寡人 提交于 2019-12-25 01:16:56

问题


VTK has typedefs for basic types (float, int, double, etc.), and it assigns an integer per type. They are specified here.

The function GetDataType(), for example in vtkDataArray returns an integer that corresponds to one of the types. I would like to compare that integer with the basic data types (float, int, double).

Is there a way of doing so, easily ?

The usage I have of this is a template class which parameter T is a scalar. I want to check if the scalar point data of a dataset has the same data type as T.

For now, what I do, is a type size comparison :

vtkDataArray *scalars = image->GetPointData()->GetScalars();
if(scalars->GetDataTypeSize() != sizeof(T))
{
  std::cerr<<"Incompatible types"<<std::endl;
}

But obviously, float and int are both of size 4, so it doesn't really work.

Any ideas ?


回答1:


After gathering information from a few places, I concluded there is no way to write it simply without creating the mapping myself between the two lists of types.

So, here is the most elegant way I found to do that :

I used the idea of norisknofun's map, but I inverted it. I didn't use std::type_index() because it seems you can get the hash_code directly from the result of typeid(). I put this mapping in a function that transform basic type to VTK type, because it can serve other purposes than just comparison (see my other post).

#include <vtkType.h>

int GetVTKType(std::size_t hash_code)
{
    static std::map<std::size_t, long> typeMap;
    if(typeMap.empty())
    {
        typeMap[typeid(void).hash_code()]               = VTK_VOID;
        typeMap[typeid(char).hash_code()]               = VTK_CHAR;
        typeMap[typeid(signed char).hash_code()]        = VTK_SIGNED_CHAR;
        typeMap[typeid(unsigned char).hash_code()]      = VTK_UNSIGNED_CHAR;
        typeMap[typeid(short).hash_code()]              = VTK_SHORT;
        typeMap[typeid(unsigned short).hash_code()]     = VTK_UNSIGNED_SHORT;
        typeMap[typeid(int).hash_code()]                = VTK_INT;
        typeMap[typeid(unsigned int).hash_code()]       = VTK_UNSIGNED_INT;
        typeMap[typeid(long).hash_code()]               = VTK_LONG;
        typeMap[typeid(unsigned long).hash_code()]      = VTK_UNSIGNED_LONG;
        typeMap[typeid(float).hash_code()]              = VTK_FLOAT;
        typeMap[typeid(double).hash_code()]             = VTK_DOUBLE;
        typeMap[typeid(std::string).hash_code()]        = VTK_STRING;
        typeMap[typeid(long long).hash_code()]          = VTK_LONG_LONG;
        typeMap[typeid(unsigned long long).hash_code()] = VTK_UNSIGNED_LONG_LONG;
        typeMap[typeid(int64_t).hash_code()]            = VTK___INT64;
        typeMap[typeid(uint64_t).hash_code()]           = VTK_UNSIGNED___INT64;
    }
    return typeMap[hash_code];
}

Therefore, to compare a vtk data type, and a basic type (my template parameter T), I do :

vtkDataArray *scalars = image->GetPointData()->GetScalars();
if(scalars->GetDataType() != GetVTKType(typeid(T).hash_code()))
{
  std::cerr<<"Incompatible types"<<std::endl;
}

Or if I want a nice comparison function as norisknofun did it, I can do :

template < class T > 
bool is_same(long vtkType)
{
  return vtkType != GetVTKType(typeid(T).hash_code())
}

// somewhere.cpp
if(!is_same<T>(scalars->GetDataType()))
{
  std::cerr<<"Incompatible types"<<std::endl;
}



回答2:


I guess you have to elaborate your own mapping. Your compiler must be c++11 compliant with RTTI activated but now most of modern compilers support this feature.

I dont know what is the c++ equivalent of 'bit', 'id_type' and 'opaque' types...

#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <cstdint>
#include <string>
#include <map>

// copy from vtk header, use #include <vtkType.h> instead
#define VTK_VOID            0
#define VTK_BIT             1
#define VTK_CHAR            2
#define VTK_SIGNED_CHAR    15
#define VTK_UNSIGNED_CHAR   3
#define VTK_SHORT           4
#define VTK_UNSIGNED_SHORT  5
#define VTK_INT             6
#define VTK_UNSIGNED_INT    7
#define VTK_LONG            8
#define VTK_UNSIGNED_LONG   9
#define VTK_FLOAT          10
#define VTK_DOUBLE         11
#define VTK_ID_TYPE        12
#define VTK_STRING         13
#define VTK_OPAQUE         14
#define VTK_LONG_LONG          16
#define VTK_UNSIGNED_LONG_LONG 17
#define VTK___INT64            18
#define VTK_UNSIGNED___INT64   19

// vtktypes
    typedef long vtktypes ;

    // standard c++ types
    typedef std::size_t   mytypes ;
    typedef std::map< vtktypes, mytypes> map_t;

template < class T > 
bool is_same(vtktypes x)
{
    static std::map< vtktypes, mytypes> _map;
    if(_map.empty())
    {
        _map[VTK_VOID           ]   = std::type_index(typeid(void)).hash_code();
        //_map[VTK_BIT              ]   = std::type_index(typeid(void)).hash_code();
        _map[VTK_CHAR           ]   = std::type_index(typeid(char)).hash_code();
        _map[VTK_SIGNED_CHAR    ]   = std::type_index(typeid(signed char)).hash_code();
        _map[VTK_UNSIGNED_CHAR  ]   = std::type_index(typeid(unsigned char)).hash_code();
        _map[VTK_SHORT          ]   = std::type_index(typeid(short)).hash_code();
        _map[VTK_UNSIGNED_SHORT ]   = std::type_index(typeid(unsigned short)).hash_code();
        _map[VTK_INT            ]   = std::type_index(typeid(int)).hash_code();
        _map[VTK_UNSIGNED_INT   ]   = std::type_index(typeid(unsigned int)).hash_code();
        _map[VTK_LONG           ]   = std::type_index(typeid(long)).hash_code();
        _map[VTK_UNSIGNED_LONG  ]   = std::type_index(typeid(unsigned long)).hash_code();
        _map[VTK_FLOAT          ]   = std::type_index(typeid(float)).hash_code();

        _map[VTK_DOUBLE         ]   = std::type_index(typeid(double)).hash_code();
        //_map[VTK_ID_TYPE          ]   = type_index(typeid()).hash_code();
        _map[VTK_STRING         ]   = std::type_index(typeid(std::string)).hash_code();
        //_map[VTK_OPAQUE           ]   = type_index(typeid(void)).hash_code();
        _map[VTK_LONG_LONG         ]= std::type_index(typeid(long long)).hash_code();
        _map[VTK_UNSIGNED_LONG_LONG]= std::type_index(typeid(unsigned long long)).hash_code();
        _map[VTK___INT64           ]= std::type_index(typeid(int64_t)).hash_code();
        _map[VTK_UNSIGNED___INT64  ]= std::type_index(typeid(uint64_t)).hash_code();
    }

    map_t::iterator it = _map.find(x);
    return (it != _map.end()) && it->second == std::type_index(typeid(T)).hash_code();
}

int main()
{
    std::cout << "is same ? " << is_same<char>(2) << std::endl ;
    std::cout << "is same ? " << is_same<std::string>(13) << std::endl ;    

    return 0;
}

In your case, you can use it like that :

vtkDataArray *scalars = image->GetPointData()->GetScalars();
if(!is_same<T>(scalars->GetDataTypeSize()))
{
  std::cerr<<"Incompatible types"<<std::endl;
}


来源:https://stackoverflow.com/questions/36476714/compare-vtk-data-types-and-basic-data-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!