diff --git a/src/VTKWriter/VTKWriter.hpp b/src/VTKWriter/VTKWriter.hpp index 16f5a1c9daa2c38aa6aaae6bb42cc4e11c39585e..a5bfcd5bca4fcd12a7b38f37bb8474e2dd7326f6 100644 --- a/src/VTKWriter/VTKWriter.hpp +++ b/src/VTKWriter/VTKWriter.hpp @@ -15,37 +15,74 @@ #include <fstream> #include "util/common.hpp" -/*! \brief Get the type +/*! \brief Get the type Old * * It convert T to a string identify the corrispondent type in VTK format * */ template <typename T> std::string getType() +{ + // Create a property string based on the type of the property + if (std::is_same<T,float>::value) + return "float"; + else if (std::is_same<T,double>::value) + return "double"; + else if (std::is_same<T,char>::value) + return "char"; + else if (std::is_same<T,unsigned char>::value) + return "unsigned_char"; + else if (std::is_same<T,short>::value) + return "short"; + else if (std::is_same<T,unsigned short>::value) + return "unsigned_short"; + else if (std::is_same<T,int>::value) + return "int"; + else if (std::is_same<T,unsigned int>::value) + return "unsigned_int"; + else if (std::is_same<T,long int>::value) + return "int"; + else if (std::is_same<T,unsigned long int>::value ) + return "unsigned_int"; + else if (std::is_same<T,bool>::value ) + return "bit"; + + return ""; +} + + + +/*! \brief Get the type + * + * It convert T to a string identify the corrispondent type in VTK format + * + */ + +template <typename T> std::string getTypeNew() { // Create a property string based on the type of the property if (std::is_same<T,float>::value) - return "float"; + return "Float32"; else if (std::is_same<T,double>::value) - return "double"; + return "Float64"; else if (std::is_same<T,char>::value) - return "char"; + return "Int8"; else if (std::is_same<T,unsigned char>::value) - return "unsigned_char"; + return "Uint8"; else if (std::is_same<T,short>::value) - return "short"; + return "Int16"; else if (std::is_same<T,unsigned short>::value) - return "unsigned_short"; + return "Uint16"; else if (std::is_same<T,int>::value) - return "int"; + return "Int32"; else if (std::is_same<T,unsigned int>::value) - return "unsigned_int"; + return "Uint32"; else if (std::is_same<T,long int>::value) - return "int"; + return "Int64"; else if (std::is_same<T,unsigned long int>::value ) - return "unsigned_int"; + return "Uint64"; else if (std::is_same<T,bool>::value ) - return "bit"; + return "Int8"; return ""; } diff --git a/src/VTKWriter/VTKWriter_grids_util.hpp b/src/VTKWriter/VTKWriter_grids_util.hpp index 2e05b26defb337db772b3d97514ec0dfd5abe41d..fa2a6e71f17697a09aca53d31597594cd8a2c5fb 100644 --- a/src/VTKWriter/VTKWriter_grids_util.hpp +++ b/src/VTKWriter/VTKWriter_grids_util.hpp @@ -71,6 +71,77 @@ struct getAttrName<ele_g,false> * */ template<unsigned int i, typename ele_g, bool has_attributes> std::string get_point_property_header_impl(const std::string & oprp, const openfpm::vector<std::string> & prop_names) +{ + //! vertex node output string + std::string v_out; + + typedef typename boost::mpl::at<typename ele_g::value_type::value_type::type,boost::mpl::int_<i>>::type ctype; + + // Check if T is a supported format + // for now we support only scalar of native type + if (std::rank<ctype>::value == 1) + { + if (std::extent<ctype>::value <= 3) + { + //Get type of the property + std::string type = getType<typename std::remove_all_extents<ctype>::type>(); + + // if the type is not supported skip-it + if (type.size() == 0) + { +#ifndef DISABLE_ALL_RTTI + std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the type " << demangle(typeid(ctype).name()) << " is not supported by vtk\n"; +#endif + return ""; + } + + // Create point data properties + v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + } + } + else + { + std::string type = getType<typename std::remove_all_extents<ctype>::type>(); + + // if the type is not supported return + if (type.size() == 0) + { + // We check if is a custom vtk writable object + + if (is_vtk_writable<ctype>::value == true) + { + type = getType<typename vtk_type<ctype,is_custom_vtk_writable<ctype>::value>::type >(); + + // We check if it is a vector or scalar like type + if (vtk_dims<ctype>::value == 1) + v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + else + v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + } + + return v_out; + } + + // Create point data properties + v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + + // Default lookup table + v_out += "LOOKUP_TABLE default\n"; + + } + + // return the vertex list + return v_out; +} + + +/*! \brief Get the vtk properties header appending a prefix at the end + * + * \tparam has_attributes indicate if the properties have attributes name + * \param oprp prefix + * + */ +template<unsigned int i, typename ele_g, bool has_attributes> std::string get_point_property_header_impl_new(const std::string & oprp, const openfpm::vector<std::string> & prop_names,file_type ft) { //! vertex node output string std::string v_out; @@ -84,7 +155,7 @@ template<unsigned int i, typename ele_g, bool has_attributes> std::string get_po if (std::extent<ctype>::value <= 3) { //Get type of the property - std::string type = getType<typename std::remove_all_extents<ctype>::type>(); + std::string type = getTypeNew<typename std::remove_all_extents<ctype>::type>(); // if the type is not supported skip-it if (type.size() == 0) @@ -96,12 +167,20 @@ template<unsigned int i, typename ele_g, bool has_attributes> std::string get_po } // Create point data properties - v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + v_out += " <DataArray type=\""+type+"\" Name=\""+getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp)+"\""+" NumberOfComponents=\"3\""; + if(ft==file_type::ASCII){ + v_out+=" format=\"ascii\">\n"; + } + else{ + v_out+=" format=\"binary\">\n"; + } + + //v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; } } else { - std::string type = getType<typename std::remove_all_extents<ctype>::type>(); + std::string type = getTypeNew<typename std::remove_all_extents<ctype>::type>(); // if the type is not supported return if (type.size() == 0) @@ -110,23 +189,45 @@ template<unsigned int i, typename ele_g, bool has_attributes> std::string get_po if (is_vtk_writable<ctype>::value == true) { - type = getType<typename vtk_type<ctype,is_custom_vtk_writable<ctype>::value>::type >(); + type = getTypeNew<typename vtk_type<ctype,is_custom_vtk_writable<ctype>::value>::type >(); // We check if it is a vector or scalar like type - if (vtk_dims<ctype>::value == 1) - v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; - else - v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + if (vtk_dims<ctype>::value == 1) { + v_out += " <DataArray type=\"" + type + "\" Name=\"" + + getAttrName<ele_g, has_attributes>::get(i, prop_names, oprp) + "\""; + if (ft == file_type::ASCII) { + v_out += " format=\"ascii\">\n"; + } else { + v_out += " format=\"binary\">\n"; + } + //v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + } + else{ + v_out += " <DataArray type=\""+type+"\" Name=\""+getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp)+"\""+" NumberOfComponents=\"3\""; + if(ft==file_type::ASCII){ + v_out+=" format=\"ascii\">\n"; + } + else{ + v_out+=" format=\"binary\">\n"; + } + //v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; + } } return v_out; } // Create point data properties - v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; - + v_out += " <DataArray type=\"" + type + "\" Name=\"" +getAttrName<ele_g, has_attributes>::get(i, prop_names, oprp) + "\""; + if (ft == file_type::ASCII) { + v_out += " format=\"ascii\">\n"; + } + else { + v_out += " format=\"binary\">\n"; + } + //v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n"; // Default lookup table - v_out += "LOOKUP_TABLE default\n"; + //v_out += "LOOKUP_TABLE default\n"; } @@ -219,6 +320,88 @@ public: } }; +/*! \brief Write the vectror property + * + * \tparam dim Dimensionality of the property + * + */ +template<unsigned int dim, typename T> +class prop_write_out_new +{ +public: + + template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it, file_type ft) + { + + if (ft == file_type::ASCII) + { + // Print the properties + for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++) + { + v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1)) + " "; + } + if (vtk_dims<T>::value == 2) + { + v_out += "0.0"; + } + v_out += "\n"; + } + else + { + typedef decltype(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(0)) ctype_; + typedef typename std::remove_reference<ctype_>::type ctype; + + // Print the properties + for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++) + { + typename is_vtk_writable<ctype>::base tmp = vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1); + v_out.append((const char *)&tmp,sizeof(tmp)); + } + if (vtk_dims<T>::value == 2) + { + typename is_vtk_writable<ctype>::base zero = 0.0; + v_out.append((const char *)&zero,sizeof(zero)); + } + } + } +}; + +/*! \brief Write the scalar property + * + * + */ +template<typename T> +class prop_write_out_new<1,T> +{ +public: + + /*! \brief Write the property + * + * \param v_out output string of the property + * \param vg vector of properties + * \param k data-set to output + * \param it iterator with the point to output + * \param ft output type BINARY or ASCII + * + */ + template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it, file_type ft) + { + typedef decltype(vg.get(k).g.template get<I::value>(it.get())) ctype_; + typedef typename std::remove_const<typename std::remove_reference<ctype_>::type>::type ctype; + + if (ft == file_type::ASCII) + { + // Print the property + v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())) + "\n"; + } + else + { + typename is_vtk_writable<ctype>::base tmp = vg.get(k).g.template get<I::value>(it.get()); + v_out.append((const char *)&tmp,sizeof(tmp)); + } + } +}; + /*! \brief This class is an helper to create properties output from scalar and compile-time array elements * @@ -231,6 +414,218 @@ public: */ template<typename I, typename ele_g, typename St, typename T, bool is_writable> struct meta_prop +{ + /*! \brief Write a vtk compatible type into vtk format + * + * \param vg array of elements to write + * \param v_out string containing the string + * \param prop_names property names + * \param ft ASCII or BINARY + * + */ + inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) + { + // actual string size + size_t sz = v_out.size(); + + // Produce the point properties header + v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names); + + // If the output has changed, we have to write the properties + if (v_out.size() != sz) + { + // Produce point data + + for (size_t k = 0 ; k < vg.size() ; k++) + { + //! Get a vertex iterator + auto it = vg.get(k).g.getIterator(); + + // if there is the next element + while (it.isNext()) + { + prop_write_out<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_out,vg,k,it,ft); + + // increment the iterator and counter + ++it; + } + } + + if (ft == file_type::BINARY) + v_out += "\n"; + } + } +}; + +//! Partial specialization for N=1 1D-Array +template<typename I, typename ele_g, typename St, typename T, size_t N1, bool is_writable> +struct meta_prop<I, ele_g,St,T[N1],is_writable> +{ + /*! \brief Write a vtk compatible type into vtk format + * + * \param vg array of elements to write + * \param v_out string containing the string + * \param prop_names properties name + * \param ft ASCII or BINARY + * + */ + inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names , file_type ft) + { + // actual string size + size_t sz = v_out.size(); + + // Produce the point properties header + v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names); + + // If the output has changed, we have to write the properties + if (v_out.size() != sz) + { + // Produce point data + + for (size_t k = 0 ; k < vg.size() ; k++) + { + //! Get a vertex iterator + auto it = vg.get(k).g.getIterator(); + + // if there is the next element + while (it.isNext()) + { + if (ft == file_type::ASCII) + { + // Print the properties + for (size_t i1 = 0 ; i1 < N1 ; i1++) + {v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1]) + " ";} + + if (N1 == 2) + {v_out += std::to_string((decltype(vg.get(k).g.template get<I::value>(it.get())[0])) 0);} + + v_out += "\n"; + } + else + { + T tmp; + + // Print the properties + for (size_t i1 = 0 ; i1 < N1 ; i1++) + { + tmp = vg.get(k).g.template get<I::value>(it.get())[i1]; + tmp = swap_endian_lt(tmp); + v_out.append((const char *)&tmp,sizeof(T)); + } + if (N1 == 2) + { + tmp = 0.0; + tmp = swap_endian_lt(tmp); + v_out.append((const char *)&tmp,sizeof(T)); + } + } + + // increment the iterator and counter + ++it; + } + } + if (ft == file_type::BINARY) + {v_out += "\n";} + } + } +}; + +//! Partial specialization for N=2 2D-Array +template<typename I, typename ele_g, typename St ,typename T,size_t N1,size_t N2, bool is_writable> +struct meta_prop<I, ele_g,St, T[N1][N2],is_writable> +{ + + /*! \brief Write a vtk compatible type into vtk format + * + * \param vg array of elements to write + * \param v_out string containing the string + * \param prop_names property names + * \param ft ASCII or BINARY + * + */ + inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) + { + for (size_t i1 = 0 ; i1 < N1 ; i1++) + { + for (size_t i2 = 0 ; i2 < N2 ; i2++) + { + // actual string size + size_t sz = v_out.size(); + + // Produce the point properties header + v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("_" + std::to_string(i1) + "_" + std::to_string(i2),prop_names); + + // If the output has changed, we have to write the properties + if (v_out.size() != sz) + { + // Produce point data + + for (size_t k = 0 ; k < vg.size() ; k++) + { + //! Get a vertex iterator + auto it = vg.get(k).g.getIterator(); + + // if there is the next element + while (it.isNext()) + { + T tmp; + + if (ft == file_type::ASCII) + { + // Print the property + v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1][i2]) + "\n"; + } + else + { + tmp = vg.get(k).g.template get<I::value>(it.get())[i1][i2]; + tmp = swap_endian_lt(tmp); + v_out.append((const char *)&tmp,sizeof(tmp)); + } + + // increment the iterator and counter + ++it; + } + } + + if (ft == file_type::BINARY) + v_out += "\n"; + } + } + } + } +}; + + +//! Specialication when is not writable +template<typename I, typename ele_g, typename St, typename T> +struct meta_prop<I,ele_g,St,T,false> +{ + + /*! \brief Write a vtk compatible type into vtk format + * + * \param vg array of elements to write + * \param v_out string containing the string + * \param prop_names properties name + * \param ft ASCII or BINARY + * + */ + inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) + { + } +}; + + +/*! \brief This class is an helper to create properties output from scalar and compile-time array elements + * + * \tparam I It is an boost::mpl::int_ that indicate which property we are writing + * \tparam ele_g element type that store the grid information + * \tparam St type of space where the grid live + * \tparam T the type of the property + * \tparam is_writable flag that indicate if a property is writable + * + */ +template<typename I, typename ele_g, typename St, typename T, bool is_writable> +struct meta_prop_new { /*! \brief Write a vtk compatible type into vtk format * @@ -240,19 +635,22 @@ struct meta_prop * \param ft ASCII or BINARY * */ - inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) + inline meta_prop_new(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) { // actual string size size_t sz = v_out.size(); + std::string v_outToEncode,v_Encoded; // Produce the point properties header - v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names); + v_out += get_point_property_header_impl_new<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names,ft); // If the output has changed, we have to write the properties if (v_out.size() != sz) { + if (ft == file_type::BINARY) { + v_outToEncode.append(8,0); + } // Produce point data - for (size_t k = 0 ; k < vg.size() ; k++) { //! Get a vertex iterator @@ -261,22 +659,33 @@ struct meta_prop // if there is the next element while (it.isNext()) { - prop_write_out<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_out,vg,k,it,ft); + prop_write_out_new<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_outToEncode,vg,k,it,ft); // increment the iterator and counter ++it; } } - if (ft == file_type::BINARY) - v_out += "\n"; + if (ft == file_type::BINARY) + { + *(size_t *) &v_outToEncode[0] = v_outToEncode.size()-sizeof(size_t); + v_Encoded.resize(v_outToEncode.size()/3*4+4); + size_t sz=EncodeToBase64((const unsigned char*)&v_outToEncode[0],v_outToEncode.size(),(unsigned char *)&v_Encoded[0],0); + v_Encoded.resize(sz); + v_out += v_Encoded + "\n"; + } + else{ + v_out += v_outToEncode; + }; + v_out += " </DataArray>\n"; + } } }; //! Partial specialization for N=1 1D-Array template<typename I, typename ele_g, typename St, typename T, size_t N1, bool is_writable> -struct meta_prop<I, ele_g,St,T[N1],is_writable> +struct meta_prop_new<I, ele_g,St,T[N1],is_writable> { /*! \brief Write a vtk compatible type into vtk format * @@ -286,17 +695,21 @@ struct meta_prop<I, ele_g,St,T[N1],is_writable> * \param ft ASCII or BINARY * */ - inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names , file_type ft) + inline meta_prop_new(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names , file_type ft) { // actual string size size_t sz = v_out.size(); + std::string v_outToEncode,v_Encoded; // Produce the point properties header - v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names); + v_out += get_point_property_header_impl_new<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names,ft); // If the output has changed, we have to write the properties if (v_out.size() != sz) { + if (ft == file_type::BINARY) { + v_outToEncode.append(8,0); + } // Produce point data for (size_t k = 0 ; k < vg.size() ; k++) @@ -311,12 +724,12 @@ struct meta_prop<I, ele_g,St,T[N1],is_writable> { // Print the properties for (size_t i1 = 0 ; i1 < N1 ; i1++) - {v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1]) + " ";} + {v_outToEncode += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1]) + " ";} if (N1 == 2) - {v_out += std::to_string((decltype(vg.get(k).g.template get<I::value>(it.get())[0])) 0);} + {v_outToEncode += std::to_string((decltype(vg.get(k).g.template get<I::value>(it.get())[0])) 0);} - v_out += "\n"; + v_outToEncode += "\n"; } else { @@ -326,14 +739,14 @@ struct meta_prop<I, ele_g,St,T[N1],is_writable> for (size_t i1 = 0 ; i1 < N1 ; i1++) { tmp = vg.get(k).g.template get<I::value>(it.get())[i1]; - tmp = swap_endian_lt(tmp); - v_out.append((const char *)&tmp,sizeof(T)); + //tmp = swap_endian_lt(tmp); + v_outToEncode.append((const char *)&tmp,sizeof(T)); } if (N1 == 2) { tmp = 0.0; - tmp = swap_endian_lt(tmp); - v_out.append((const char *)&tmp,sizeof(T)); + //tmp = swap_endian_lt(tmp); + v_outToEncode.append((const char *)&tmp,sizeof(T)); } } @@ -341,15 +754,25 @@ struct meta_prop<I, ele_g,St,T[N1],is_writable> ++it; } } - if (ft == file_type::BINARY) - {v_out += "\n";} - } + if (ft == file_type::BINARY) + { + *(size_t *) &v_outToEncode[0] = v_outToEncode.size()-sizeof(size_t); + v_Encoded.resize(v_outToEncode.size()/3*4+4); + size_t sz=EncodeToBase64((const unsigned char*)&v_outToEncode[0],v_outToEncode.size(),(unsigned char *)&v_Encoded[0],0); + v_Encoded.resize(sz); + v_out += v_Encoded + "\n"; + } + else{ + v_out += v_outToEncode; + }; + v_out += " </DataArray>\n"; + } } }; //! Partial specialization for N=2 2D-Array template<typename I, typename ele_g, typename St ,typename T,size_t N1,size_t N2, bool is_writable> -struct meta_prop<I, ele_g,St, T[N1][N2],is_writable> +struct meta_prop_new<I, ele_g,St, T[N1][N2],is_writable> { /*! \brief Write a vtk compatible type into vtk format @@ -360,21 +783,27 @@ struct meta_prop<I, ele_g,St, T[N1][N2],is_writable> * \param ft ASCII or BINARY * */ - inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) + inline meta_prop_new(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) { - for (size_t i1 = 0 ; i1 < N1 ; i1++) + std::string v_outToEncode,v_Encoded; + + for (size_t i1 = 0 ; i1 < N1 ; i1++) { for (size_t i2 = 0 ; i2 < N2 ; i2++) { + v_outToEncode.clear(); // actual string size size_t sz = v_out.size(); // Produce the point properties header - v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("_" + std::to_string(i1) + "_" + std::to_string(i2),prop_names); + v_out += get_point_property_header_impl_new<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("_" + std::to_string(i1) + "_" + std::to_string(i2),prop_names, ft); // If the output has changed, we have to write the properties if (v_out.size() != sz) { + if (ft == file_type::BINARY) { + v_outToEncode.append(8,0); + } // Produce point data for (size_t k = 0 ; k < vg.size() ; k++) @@ -390,23 +819,33 @@ struct meta_prop<I, ele_g,St, T[N1][N2],is_writable> if (ft == file_type::ASCII) { // Print the property - v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1][i2]) + "\n"; + v_outToEncode += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1][i2]) + "\n"; } else { tmp = vg.get(k).g.template get<I::value>(it.get())[i1][i2]; - tmp = swap_endian_lt(tmp); - v_out.append((const char *)&tmp,sizeof(tmp)); + //tmp = swap_endian_lt(tmp); + v_outToEncode.append((const char *)&tmp,sizeof(tmp)); } // increment the iterator and counter ++it; } } - - if (ft == file_type::BINARY) - v_out += "\n"; - } + if (ft == file_type::BINARY) + { + *(size_t *) &v_outToEncode[0] = v_outToEncode.size()-sizeof(size_t); + v_Encoded.resize(v_outToEncode.size()/3*4+4); + size_t sz=EncodeToBase64((const unsigned char*)&v_outToEncode[0],v_outToEncode.size(),(unsigned char *)&v_Encoded[0],0); + v_Encoded.resize(sz); + v_out += v_Encoded + "\n"; + } + else{ + v_out += v_outToEncode; + }; + v_out += " </DataArray>\n"; + + } } } } @@ -415,7 +854,7 @@ struct meta_prop<I, ele_g,St, T[N1][N2],is_writable> //! Specialication when is not writable template<typename I, typename ele_g, typename St, typename T> -struct meta_prop<I,ele_g,St,T,false> +struct meta_prop_new<I,ele_g,St,T,false> { /*! \brief Write a vtk compatible type into vtk format @@ -426,7 +865,7 @@ struct meta_prop<I,ele_g,St,T,false> * \param ft ASCII or BINARY * */ - inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) + inline meta_prop_new(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft) { } }; @@ -448,7 +887,7 @@ template<unsigned int dims,typename T> inline void output_point(Point<dims,T> & { // we use float so we have to convert to float auto tmp = p.get(i); - tmp = swap_endian_lt(tmp); + //tmp = swap_endian_lt(tmp); v_out.write((const char *)&tmp,sizeof(tmp)); } for ( ; i < 3 ; i++) @@ -457,26 +896,69 @@ template<unsigned int dims,typename T> inline void output_point(Point<dims,T> & /* coverity[dead_error_begin] */ T tmp = 0.0; - tmp = swap_endian_lt(tmp); + //tmp = swap_endian_lt(tmp); v_out.write((const char *)&tmp,sizeof(tmp)); } } } + +template<unsigned int dims,typename T> inline void output_point_new(Point<dims,T> & p,std::stringstream & v_out, file_type ft) +{ + if (ft == file_type::ASCII) + { + v_out << p.toString(); + size_t i = dims; + for ( ; i < 3 ; i++) + {v_out << " 0.0";} + v_out << "\n"; + } + else + { + size_t i = 0; + for ( ; i < dims ; i++) + { + // we use float so we have to convert to float + auto tmp = p.get(i); + v_out.write((const char *)&tmp,sizeof(tmp)); + } + for ( ; i < 3 ; i++) + { + // we use float so we have to convert to float + + /* coverity[dead_error_begin] */ + T tmp = 0.0; + v_out.write((const char *)&tmp,sizeof(tmp)); + } + } +} + inline void output_vertex(size_t k,std::string & v_out, file_type ft) { - if (ft == file_type::ASCII) - {v_out += "1 " + std::to_string(k) + "\n";} - else - { - int tmp; - tmp = 1; - tmp = swap_endian_lt(tmp); - v_out.append((const char *)&tmp,sizeof(int)); - tmp = k; - tmp = swap_endian_lt(tmp); - v_out.append((const char *)&tmp,sizeof(int)); - } + if (ft == file_type::ASCII) + {v_out += "1 " + std::to_string(k) + "\n";} + else + { + int tmp; + tmp = 1; + tmp = swap_endian_lt(tmp); + v_out.append((const char *)&tmp,sizeof(int)); + tmp = k; + tmp = swap_endian_lt(tmp); + v_out.append((const char *)&tmp,sizeof(int)); + } +} + +inline void output_vertex_new(size_t k,std::string & v_out, file_type ft) +{ + if (ft == file_type::ASCII) + {v_out += std::to_string(k) + "\n";} + else + { + size_t tmp; + tmp = k; + v_out.append((const char *)&tmp,sizeof(size_t)); + } } #endif /* SRC_VTKWRITER_GRIDS_UTIL_HPP_ */ diff --git a/src/VTKWriter/VTKWriter_point_set.hpp b/src/VTKWriter/VTKWriter_point_set.hpp index b7a6d1de4b248d2ec1d90f46fce867fdf7cc68b2..b31e5446650c83ac94ff4c3eff0654760e94645d 100644 --- a/src/VTKWriter/VTKWriter_point_set.hpp +++ b/src/VTKWriter/VTKWriter_point_set.hpp @@ -120,17 +120,27 @@ struct prop_out_v typedef typename boost::mpl::at<typename ele_v::value_type::value_type::type,boost::mpl::int_<T::value>>::type ptype; typedef typename std::remove_all_extents<ptype>::type base_ptype; - meta_prop<boost::mpl::int_<T::value> ,ele_v,St, ptype, is_vtk_writable<base_ptype>::value > m(vv,v_out,prop_names,ft); + meta_prop_new<boost::mpl::int_<T::value> ,ele_v,St, ptype, is_vtk_writable<base_ptype>::value > m(vv,v_out,prop_names,ft); } void lastProp() { - // Create point data properties - v_out += "SCALARS domain float\n"; - + std::string v_outToEncode,v_Encoded; + // Create point data properties + //v_out += "SCALARS domain float\n"; // Default lookup table - v_out += "LOOKUP_TABLE default\n"; - + //v_out += "LOOKUP_TABLE default\n"; + v_out += " <DataArray type=\"Float32\" Name=\"domain\""; + if (ft == file_type::ASCII) { + v_out += " format=\"ascii\">\n"; + } + else { + v_out += " format=\"binary\">\n"; + } + + if (ft == file_type::BINARY) { + v_outToEncode.append(8,0); + } // Produce point data for (size_t k = 0 ; k < vv.size() ; k++) { @@ -143,23 +153,23 @@ struct prop_out_v if (ft == file_type::ASCII) { if (it.get() < vv.get(k).mark) - v_out += "1.0\n"; + v_outToEncode += "1.0\n"; else - v_out += "0.0\n"; + v_outToEncode += "0.0\n"; } else { if (it.get() < vv.get(k).mark) { float one = 1; - one = swap_endian_lt(one); - v_out.append((const char *)&one,sizeof(int)); + //one = swap_endian_lt(one); + v_outToEncode.append((const char *)&one,sizeof(int)); } else { float zero = 0; - zero = swap_endian_lt(zero); - v_out.append((const char *)&zero,sizeof(int)); + //zero = swap_endian_lt(zero); + v_outToEncode.append((const char *)&zero,sizeof(int)); } } @@ -167,7 +177,20 @@ struct prop_out_v ++it; } } - } + if (ft == file_type::BINARY) + { + *(size_t *) &v_outToEncode[0] = v_outToEncode.size()-sizeof(size_t); + v_Encoded.resize(v_outToEncode.size()/3*4+4); + size_t sz=EncodeToBase64((const unsigned char*)&v_outToEncode[0],v_outToEncode.size(),(unsigned char *)&v_Encoded[0],0); + v_Encoded.resize(sz); + v_out += v_Encoded + "\n"; + } + else{ + v_out += v_outToEncode; + }; + v_out+=" </DataArray>\n"; + } + }; /*! @@ -212,14 +235,24 @@ class VTKWriter<pair,VECTOR_POINTS> * \return a string that define the vertex properties in graphML format * */ - std::string get_vertex_properties_list() + std::string get_vertex_properties_list(file_type & opt) { //! vertex property output string std::string v_out; - // write the number of vertex - v_out += "VERTICES " + std::to_string(get_total()) + " " + std::to_string(get_total() * 2) + "\n"; + v_out += " <Verts>\n"; + if (opt == file_type::ASCII) + + { + v_out+=" <DataArray type=\"Int64\" Name=\"connectivity\" format=\"ascii\">\n"; + } + else + { + v_out+=" <DataArray type=\"Int64\" Name=\"connectivity\" format=\"binary\">\n"; + } + // write the number of vertex + //v_out += "VERTICES " + std::to_string(get_total()) + " " + std::to_string(get_total() * 2) + "\n"; // return the vertex properties string return v_out; } @@ -239,7 +272,7 @@ class VTKWriter<pair,VECTOR_POINTS> // write the number of vertex - v_out += "POINTS " + std::to_string(get_total()) + " " + getType<typename pair::first::value_type::coord_type>() + "\n"; + v_out += " <Piece NumberOfPoints=\"" + std::to_string(get_total()) + "\" " +"NumberOfVerts=\"" + std::to_string(get_total()) + "\">\n";// + getType<typename pair::first::value_type::coord_type>() + "\n"; // return the vertex properties string return v_out; @@ -252,14 +285,31 @@ class VTKWriter<pair,VECTOR_POINTS> * \return the list of points * */ - std::string get_point_list(file_type ft) + std::string get_point_list(file_type & opt) { //! vertex node output string std::stringstream v_out; + v_out<<" <Points>\n"; + + if (opt == file_type::ASCII) + { + v_out<<" <DataArray type=\"Float64\" Name=\"Points\" NumberOfComponents=\"3\" format=\"ascii\">\n"; + } + else + { + v_out<<" <DataArray type=\"Float64\" Name=\"Points\" NumberOfComponents=\"3\" format=\"binary\">\n"; + } + + std::stringstream binaryToEncode; //! For each defined grid + if (opt == file_type::BINARY) + { + size_t tmp=0; + binaryToEncode.write((const char *)&tmp,sizeof(tmp)); + } - for (size_t i = 0 ; i < vps.size() ; i++) + for (size_t i = 0 ; i < vps.size() ; i++) { //! write the particle position auto it = vps.get(i).g.getIterator(); @@ -270,17 +320,28 @@ class VTKWriter<pair,VECTOR_POINTS> Point<pair::first::value_type::dims,typename pair::first::value_type::coord_type> p; p = vps.get(i).g.get(it.get()); - output_point<pair::first::value_type::dims,typename pair::first::value_type::coord_type>(p,v_out,ft); + output_point_new<pair::first::value_type::dims,typename pair::first::value_type::coord_type>(p,binaryToEncode,opt); // increment the iterator and counter ++it; } } - //! In case of binary we have to add a new line at the end of the list - if (ft == file_type::BINARY) - v_out << std::endl; - + if (opt == file_type::BINARY){ + std::string buffer_out,buffer_bin; + buffer_bin=binaryToEncode.str(); + *(size_t *)&buffer_bin[0]=buffer_bin.size()-8; + buffer_out.resize(buffer_bin.size()/3*4+4); + unsigned long sz = EncodeToBase64((const unsigned char*)&buffer_bin[0],buffer_bin.size(),(unsigned char*)&buffer_out[0],0); + buffer_out.resize(sz); + v_out << buffer_out<<std::endl; + } + else + { + v_out<<binaryToEncode.str(); + } + v_out<<" </DataArray>\n"; + v_out<<" </Points>\n"; // return the vertex list return v_out.str(); } @@ -295,10 +356,12 @@ class VTKWriter<pair,VECTOR_POINTS> std::string get_vertex_list(file_type ft) { // vertex node output string - std::string v_out; - - size_t k = 0; + std::string v_out,v_outToEncode,v_Encoded; + size_t k = 0; + if (ft == file_type::BINARY) { + v_outToEncode.append(8,0); + } for (size_t i = 0 ; i < vps.size() ; i++) { //! For each grid point create a vertex @@ -306,17 +369,66 @@ class VTKWriter<pair,VECTOR_POINTS> while (it.isNext()) { - output_vertex(k,v_out,ft); + output_vertex_new(k,v_outToEncode,ft); ++k; ++it; } } - //! In case of binary we have to add a new line at the end of the list if (ft == file_type::BINARY) - {v_out += "\n";} - + { + *(size_t *) &v_outToEncode[0] = v_outToEncode.size()-sizeof(size_t); + v_Encoded.resize(v_outToEncode.size()/3*4+4); + size_t sz=EncodeToBase64((const unsigned char*)&v_outToEncode[0],v_outToEncode.size(),(unsigned char *)&v_Encoded[0],0); + v_Encoded.resize(sz); + v_out += v_Encoded + "\n"; + } + else{ + v_out += v_outToEncode; + }; + v_out += " </DataArray>\n"; + v_out += " <DataArray type=\"Int64\" Name=\"offsets\" "; + + if (ft == file_type::ASCII) + { + v_out += "format=\"ascii\">\n"; + } + else{ + v_out += "format=\"binary\">\n"; + } + + k=0; + v_outToEncode.clear(); + if (ft == file_type::BINARY) { + v_outToEncode.append(8,0); + } + + for (size_t i = 0 ; i < vps.size() ; i++) + { + //! For each grid point create a vertex + auto it = vps.get(i).g.getIterator(); + while (it.isNext()) + { + output_vertex_new(k+1,v_outToEncode,ft); + + ++k; + ++it; + } + } + if (ft == file_type::BINARY) + { + *(size_t *) &v_outToEncode[0] = v_outToEncode.size()-sizeof(size_t); + v_Encoded.resize(v_outToEncode.size()/3*4+4); + size_t sz=EncodeToBase64((const unsigned char*)&v_outToEncode[0],v_outToEncode.size(),(unsigned char *)&v_Encoded[0],0); + v_Encoded.resize(sz); + v_out += v_Encoded + "\n"; + } + else{ + v_out += v_outToEncode; + }; + v_out += " </DataArray>\n"; + v_out += " </Verts>\n"; // return the vertex list return v_out; } @@ -330,11 +442,14 @@ class VTKWriter<pair,VECTOR_POINTS> { std::string v_out; - v_out += "POINT_DATA " + std::to_string(get_total()) + "\n"; + v_out += " <PointData>\n"; return v_out; } - + struct doubleint{ + long int i; + double d; + }; /*! \brief return the meta data string * * \param meta_data string with the meta-data to add @@ -357,18 +472,35 @@ class VTKWriter<pair,VECTOR_POINTS> if (exist == true) { - meta_string += "FIELD FieldData 1\n"; - meta_string += "TIME 1 1 double\n"; - if (opt == file_type::ASCII) - {meta_string += std::to_string(time);} + //<DataArray type="Float64" Name="TimeValue" NumberOfTuples="1" format="ascii" RangeMin="2" RangeMax="2"> + //meta_string += ""; + meta_string += " <FieldData>\n"; + + if (opt == file_type::ASCII) + { meta_string += " <DataArray type=\"Float64\" Name=\"TimeValue\" NumberOfTuples=\"1\" format=\"ascii\">\n"; + meta_string += std::to_string(time); + } else { - time = swap_endian_lt(time); - meta_string.append((const char *)&time,sizeof(double)); + meta_string += " <DataArray type=\"Float64\" Name=\"TimeValue\" NumberOfTuples=\"1\" format=\"binary\">\n"; + + //time = swap_endian_lt(time); + unsigned char time_string[24];//= base64_encode((const unsigned char*)&time,6); + //const unsigned char Time=(const unsigned char)time; + doubleint timeInit; + timeInit.i=8; + timeInit.d=time; + size_t sz=EncodeToBase64((const unsigned char*)&timeInit,16,time_string,0); + //meta_string.append((const char *)&time,sizeof(double)); + //meta_string += time_string; + meta_string.append((const char *)time_string,sz); } meta_string += "\n"; + meta_string += " </DataArray>\n"; + meta_string += " </FieldData>\n"; } + return meta_string; } @@ -437,17 +569,18 @@ public: std::string point_data; // VTK header - vtk_header = "# vtk DataFile Version 3.0\n" - + f_name + "\n"; + vtk_header = "<VTKFile type=\"PolyData\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">\n"; + + vtk_header +=" <PolyData>\n"; - // Choose if binary or ASCII - if (ft == file_type::ASCII) + // Choose if binary or ASCII +/* if (ft == file_type::ASCII) {vtk_header += "ASCII\n";} else - {vtk_header += "BINARY\n";} + {vtk_header += "BINARY\n";}*/ // Data type for graph is DATASET POLYDATA - vtk_header += "DATASET POLYDATA\n"; + //vtk_header += "DATASET POLYDATA\n"; vtk_header += add_meta_data(meta_data,ft); @@ -458,7 +591,7 @@ public: point_list = get_point_list(ft); // vertex properties header - vertex_prop_header = get_vertex_properties_list(); + vertex_prop_header = get_vertex_properties_list(ft); // Get vertex list vertex_list = get_vertex_list(ft); @@ -478,8 +611,9 @@ public: // Add the last property pp.lastProp(); + std::string closingFile=" </PointData>\n </Piece>\n </PolyData>\n</VTKFile>"; - // write the file + // write the file std::ofstream ofs(file); // Check if the file is open @@ -487,7 +621,7 @@ public: {std::cerr << "Error cannot create the VTK file: " + file + "\n";} ofs << vtk_header << point_prop_header << point_list << - vertex_prop_header << vertex_list << point_data_header << point_data; + vertex_prop_header << vertex_list << point_data_header << point_data << closingFile; // Close the file diff --git a/src/VTKWriter/VTKWriter_unit_tests.hpp b/src/VTKWriter/VTKWriter_unit_tests.hpp index b123d40c8730a1598af01adc4e4aaba110c5786b..1b857f81325df4fe929f731552a753b6e541c478 100644 --- a/src/VTKWriter/VTKWriter_unit_tests.hpp +++ b/src/VTKWriter/VTKWriter_unit_tests.hpp @@ -1017,14 +1017,14 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set ) vtk_v.add(v3ps,v3pp,90); openfpm::vector<std::string> prp_names; - vtk_v.write("vtk_points.vtk",prp_names); + vtk_v.write("vtk_points.vtp",prp_names); #ifndef SE_CLASS3 bool test = true; // Check that match - test = compare("vtk_points.vtk","test_data/vtk_points_test.vtk"); + test = compare("vtk_points.vtp","test_data/vtk_points_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1033,12 +1033,12 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,Point<3,float>>>>,VECTOR_POINTS> vtk_v2; vtk_v2.add(v1ps,v4pp,75); - vtk_v2.write("vtk_points_pp.vtk",prp_names); + vtk_v2.write("vtk_points_pp.vtp",prp_names); #ifndef SE_CLASS3 // Check that match - test = compare("vtk_points_pp.vtk","test_data/vtk_points_pp_test.vtk"); + test = compare("vtk_points_pp.vtp","test_data/vtk_points_pp_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1047,15 +1047,18 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,Point<3,float>>>>,VECTOR_POINTS> vtk_v3; vtk_v3.add(v1ps,v4pp,75); - vtk_v3.write("vtk_points_pp_header.vtk",prp_names,"points","time=5.123"); + vtk_v3.write("vtk_points_pp_header.vtp",prp_names,"points","time=5.123"); // We try binary - vtk_v3.write("vtk_points_pp_header_bin.vtk",prp_names,"points","time=5.123",file_type::BINARY); + vtk_v3.write("vtk_points_pp_header_bin.vtp",prp_names,"points","time=5.123",file_type::BINARY); #ifndef SE_CLASS3 // Check that match - test = compare("vtk_points_pp_header.vtk","test_data/vtk_points_pp_header_test.vtk"); + test = compare("vtk_points_pp_header.vtp","test_data/vtk_points_pp_header_test.vtp"); + BOOST_REQUIRE_EQUAL(test,true); + + test = compare("vtk_points_pp_header_bin.vtp","test_data/vtk_points_pp_header_bin_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1102,12 +1105,12 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_properties ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,float[3]>>>,VECTOR_POINTS> vtk_v; vtk_v.add(v1ps,v1pp,75); openfpm::vector<std::string> prp_names({"scalar","vector"}); - vtk_v.write("vtk_points_with_prp_names.vtk",prp_names); + vtk_v.write("vtk_points_with_prp_names.vtp",prp_names); #ifndef SE_CLASS3 // Check that match - bool test = compare("vtk_points_with_prp_names.vtk","test_data/vtk_points_with_prp_names_test.vtk"); + bool test = compare("vtk_points_with_prp_names.vtp","test_data/vtk_points_with_prp_names_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1188,17 +1191,17 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) vtk_v.add(v3ps,v3pp,90); openfpm::vector<std::string> prp_names; - vtk_v.write("vtk_points_bin.vtk",prp_names,"vtk output","",file_type::BINARY); - vtk_v.write("vtk_points_bin2.vtk",prp_names,"vtk output","",file_type::BINARY); + vtk_v.write("vtk_points_bin.vtp",prp_names,"vtk output","",file_type::BINARY); + vtk_v.write("vtk_points_bin2.vtp",prp_names,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 bool test = true; // Check that match - test = compare("vtk_points_bin.vtk","test_data/vtk_points_bin_test.vtk"); + test = compare("vtk_points_bin.vtp","test_data/vtk_points_bin_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); - test = compare("vtk_points_bin2.vtk","test_data/vtk_points_bin_test.vtk"); + test = compare("vtk_points_bin2.vtp","test_data/vtk_points_bin_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1207,12 +1210,12 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,Point<3,float>>>>,VECTOR_POINTS> vtk_v2; vtk_v2.add(v1ps,v4pp,75); - vtk_v2.write("vtk_points_pp_bin.vtk",prp_names,"vtk output","",file_type::BINARY); + vtk_v2.write("vtk_points_pp_bin.vtp",prp_names,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 // Check that match - test = compare("vtk_points_pp_bin.vtk","test_data/vtk_points_pp_bin_test.vtk"); + test = compare("vtk_points_pp_bin.vtp","test_data/vtk_points_pp_bin_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1303,14 +1306,14 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) openfpm::vector<std::string> stub; - vtk_v.write("vtk_points_2d_bin.vtk",stub,"vtk output","",file_type::BINARY); + vtk_v.write("vtk_points_2d_bin.vtp",stub,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 bool test = true; // Check that match - test = compare("vtk_points_2d_bin.vtk","test_data/vtk_points_2d_bin_test.vtk"); + test = compare("vtk_points_2d_bin.vtp","test_data/vtk_points_2d_bin_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif @@ -1319,12 +1322,12 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<2,double>>,openfpm::vector<aggregate<float[3],double[2]>>>,VECTOR_POINTS> vtk_v2; vtk_v2.add(v1ps,v4pp,75); - vtk_v2.write("vtk_points_2d_pp_bin.vtk",stub,"vtk output","",file_type::BINARY); + vtk_v2.write("vtk_points_2d_pp_bin.vtp",stub,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 // Check that match - test = compare("vtk_points_2d_pp_bin.vtk","test_data/vtk_points_2d_pp_bin_test.vtk"); + test = compare("vtk_points_2d_pp_bin.vtp","test_data/vtk_points_2d_pp_bin_test.vtp"); BOOST_REQUIRE_EQUAL(test,true); #endif diff --git a/src/util/util.hpp b/src/util/util.hpp index f46137ba30972114e1b29f91c73c534f4fd78085..f46f3f76842e8ecf78a8aed5868b65bd977b8e59 100644 --- a/src/util/util.hpp +++ b/src/util/util.hpp @@ -176,4 +176,215 @@ static inline bool hasEnding (std::string const &fullString, std::string const & {return false;} } +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +/*! \brief Encode to base64 + * + * \param Byte String to encode + * \param Number of bytes to encode + * + */ +/*std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + + } + + return ret; + +} + +*//*! \brief Decode base64 + * + * \param Coded string + * + *//* +std::string base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; +}*/ + + +static const unsigned char vtkBase64UtilitiesEncodeTable[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +//---------------------------------------------------------------------------- +inline static unsigned char vtkBase64UtilitiesEncodeChar(unsigned char c) +{ + assert( c < 65 ); + return vtkBase64UtilitiesEncodeTable[c]; +} + +//---------------------------------------------------------------------------- +void EncodeTriplet(unsigned char i0, + unsigned char i1, + unsigned char i2, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3) +{ + *o0 = vtkBase64UtilitiesEncodeChar((i0 >> 2) & 0x3F); + *o1 = vtkBase64UtilitiesEncodeChar(((i0 << 4) & 0x30)|((i1 >> 4) & 0x0F)); + *o2 = vtkBase64UtilitiesEncodeChar(((i1 << 2) & 0x3C)|((i2 >> 6) & 0x03)); + *o3 = vtkBase64UtilitiesEncodeChar(i2 & 0x3F); +} + +//---------------------------------------------------------------------------- +void EncodePair(unsigned char i0, + unsigned char i1, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3) +{ + *o0 = vtkBase64UtilitiesEncodeChar((i0 >> 2) & 0x3F); + *o1 = vtkBase64UtilitiesEncodeChar(((i0 << 4) & 0x30)|((i1 >> 4) & 0x0F)); + *o2 = vtkBase64UtilitiesEncodeChar(((i1 << 2) & 0x3C)); + *o3 = '='; +} + +//---------------------------------------------------------------------------- +void EncodeSingle(unsigned char i0, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3) +{ + *o0 = vtkBase64UtilitiesEncodeChar((i0 >> 2) & 0x3F); + *o1 = vtkBase64UtilitiesEncodeChar(((i0 << 4) & 0x30)); + *o2 = '='; + *o3 = '='; +} + +//---------------------------------------------------------------------------- +unsigned long EncodeToBase64(const unsigned char *input, + unsigned long length, + unsigned char *output, + int mark_end) +{ + + const unsigned char *ptr = input; + const unsigned char *end = input + length; + unsigned char *optr = output; + + // Encode complete triplet + + while ((end - ptr) >= 3) + { + EncodeTriplet(ptr[0], ptr[1], ptr[2], + &optr[0], &optr[1], &optr[2], &optr[3]); + ptr += 3; + optr += 4; + } + + // Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. + + if (end - ptr == 2) + { + EncodePair(ptr[0], ptr[1], + &optr[0], &optr[1], &optr[2], &optr[3]); + optr += 4; + } + + // Encodes a 1-byte ending into 2 bytes and 2 pad bytes + + else if (end - ptr == 1) + { + EncodeSingle(ptr[0], + &optr[0], &optr[1], &optr[2], &optr[3]); + optr += 4; + } + + // Do we need to mark the end + + else if (mark_end) + { + optr[0] = optr[1] = optr[2] = optr[3] = '='; + optr += 4; + } + + return optr - output; +} + + #endif /* UTIL_HPP_ */