VTKWriter_point_set.hpp 8.79 KB
Newer Older
incardon's avatar
incardon committed
1
/*
Pietro Incardona's avatar
Pietro Incardona committed
2
 * VTKWriter_point_set.hpp
incardon's avatar
incardon committed
3
 *
Pietro Incardona's avatar
Pietro Incardona committed
4 5
 *  Created on: Feb 6, 2016
 *      Author: i-bird
incardon's avatar
incardon committed
6 7
 */

Pietro Incardona's avatar
Pietro Incardona committed
8 9
#ifndef OPENFPM_IO_SRC_VTKWRITER_POINT_SET_HPP_
#define OPENFPM_IO_SRC_VTKWRITER_POINT_SET_HPP_
incardon's avatar
incardon committed
10

11
#include <cstddef>
incardon's avatar
incardon committed
12 13
#include <boost/mpl/pair.hpp>
#include "VTKWriter_grids_util.hpp"
Pietro Incardona's avatar
Pietro Incardona committed
14
#include "is_vtk_writable.hpp"
15
#include <string>
incardon's avatar
incardon committed
16

17
/*! \brief Store a reference to the vector position
18
 *
Pietro Incardona's avatar
Pietro Incardona committed
19
 * \tparam Vps Type of vector that store the position of the particles
20 21
 *
 */
Pietro Incardona's avatar
Pietro Incardona committed
22 23
template <typename Vps>
class ele_vps
incardon's avatar
incardon committed
24 25 26
{
public:

27
	//! type of vector that store the particle position
Pietro Incardona's avatar
Pietro Incardona committed
28
	typedef Vps value_type;
incardon's avatar
incardon committed
29

30
	//! particle position vector
Pietro Incardona's avatar
Pietro Incardona committed
31 32
	const Vps & g;

33
	//! ghost marker
Pietro Incardona's avatar
Pietro Incardona committed
34 35
	size_t mark;

36
	//! constructor
Pietro Incardona's avatar
Pietro Incardona committed
37 38
	ele_vps(const Vps & g, size_t mark)
	:g(g),mark(mark)
incardon's avatar
incardon committed
39 40 41 42
	{}

};

43
/*! \brief Store a reference to the vector properties
Pietro Incardona's avatar
Pietro Incardona committed
44 45 46 47 48 49 50 51 52
 *
 * \tparam Vpp Type of vector that store the property of the particles
 *
 */
template <typename Vpp>
class ele_vpp
{
public:

53
	//! type of vector that store the particle properties
Pietro Incardona's avatar
Pietro Incardona committed
54 55
	typedef Vpp value_type;

56 57

	//! Reference to the particle properties
Pietro Incardona's avatar
Pietro Incardona committed
58 59
	const Vpp & g;

60
	//! ghost marker
Pietro Incardona's avatar
Pietro Incardona committed
61 62
	size_t mark;

63
	//! constructor
Pietro Incardona's avatar
Pietro Incardona committed
64 65 66 67 68
	ele_vpp(const Vpp & vpp, size_t mark)
	:g(vpp),mark(mark)
	{}

};
incardon's avatar
incardon committed
69 70 71 72 73 74


/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
Pietro Incardona's avatar
Pietro Incardona committed
75 76 77
 * Is mainly used to produce an output for each property
 *
 * \tparam ele_v It is the class ele_v that store the couple vector of position and property
incardon's avatar
incardon committed
78 79 80
 *
 *
 */
Pietro Incardona's avatar
Pietro Incardona committed
81 82
template<typename ele_v, typename St>
struct prop_out_v
incardon's avatar
incardon committed
83
{
84
	//! property output string
incardon's avatar
incardon committed
85 86
	std::string & v_out;

87
	//! vector that we are processing
Pietro Incardona's avatar
Pietro Incardona committed
88
	const openfpm::vector_std< ele_v > & vv;
incardon's avatar
incardon committed
89 90 91 92

	/*! \brief constructor
	 *
	 * \param v_out string to fill with the vertex properties
93
	 * \param vv vector we are processing
incardon's avatar
incardon committed
94 95
	 *
	 */
Pietro Incardona's avatar
Pietro Incardona committed
96 97
	prop_out_v(std::string & v_out, const openfpm::vector_std< ele_v > & vv)
	:v_out(v_out),vv(vv)
incardon's avatar
incardon committed
98 99 100 101 102 103
	{};

	//! It produce an output for each property
    template<typename T>
    void operator()(T& t) const
    {
Pietro Incardona's avatar
Pietro Incardona committed
104
    	typedef typename boost::mpl::at<typename ele_v::value_type::value_type::type,boost::mpl::int_<T::value>>::type ptype;
Pietro Incardona's avatar
Pietro Incardona committed
105
    	typedef typename std::remove_all_extents<ptype>::type base_ptype;
incardon's avatar
incardon committed
106

Pietro Incardona's avatar
Pietro Incardona committed
107
    	meta_prop<boost::mpl::int_<T::value> ,ele_v,St, ptype, is_vtk_writable<base_ptype>::value > m(vv,v_out);
incardon's avatar
incardon committed
108
    }
incardon's avatar
incardon committed
109 110 111 112 113 114 115 116 117 118

    void lastProp()
	{
		// Create point data properties
		v_out += "SCALARS domain float\n";

		// Default lookup table
		v_out += "LOOKUP_TABLE default\n";

		// Produce point data
Pietro Incardona's avatar
Pietro Incardona committed
119
		for (size_t k = 0 ; k < vv.size() ; k++)
incardon's avatar
incardon committed
120 121
		{
			//! Get a vertex iterator
Pietro Incardona's avatar
Pietro Incardona committed
122
			auto it = vv.get(k).g.getIterator();
incardon's avatar
incardon committed
123 124 125 126

			// if there is the next element
			while (it.isNext())
			{
Pietro Incardona's avatar
Pietro Incardona committed
127
				if (it.get() < vv.get(k).mark)
incardon's avatar
incardon committed
128 129 130 131 132 133 134 135 136
					v_out += "1.0\n";
				else
					v_out += "0.0\n";

				// increment the iterator and counter
				++it;
			}
		}
	}
incardon's avatar
incardon committed
137 138 139 140
};

/*!
 *
Pietro Incardona's avatar
Pietro Incardona committed
141
 * It write a VTK format file for a list of grids defined on a space
incardon's avatar
incardon committed
142 143 144
 *
 * \tparam boost::mpl::pair<G,S>
 *
Pietro Incardona's avatar
Pietro Incardona committed
145 146
 * where G is the type of the vector containing the properties, S is the
 * type of vector containing the particle positions
incardon's avatar
incardon committed
147 148 149
 *
 */
template <typename pair>
Pietro Incardona's avatar
Pietro Incardona committed
150
class VTKWriter<pair,VECTOR_POINTS>
incardon's avatar
incardon committed
151
{
152
	//! Vector of position
Pietro Incardona's avatar
Pietro Incardona committed
153
	openfpm::vector< ele_vps<typename pair::first >> vps;
154
	//! Vector of properties
Pietro Incardona's avatar
Pietro Incardona committed
155
	openfpm::vector< ele_vpp<typename pair::second>> vpp;
incardon's avatar
incardon committed
156 157 158 159 160 161 162 163 164 165 166

	/*! \brief Get the total number of points
	 *
	 * \return the total number
	 *
	 */
	size_t get_total()
	{
		size_t tot = 0;

		//! Calculate the full number of vertices
Pietro Incardona's avatar
Pietro Incardona committed
167
		for (size_t i = 0 ; i < vps.size() ; i++)
incardon's avatar
incardon committed
168
		{
Pietro Incardona's avatar
Pietro Incardona committed
169
			tot += vps.get(i).g.size();
incardon's avatar
incardon committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
		}
		return tot;
	}

	/*! \brief It get the vertex properties list
	 *
	 * It get the vertex properties list of the vertex defined as VTK header
	 *
	 * \return a string that define the vertex properties in graphML format
	 *
	 */
	std::string get_vertex_properties_list()
	{
		//! vertex property output string
		std::string v_out;

		// write the number of vertex
incardon's avatar
incardon committed
187
		v_out += "VERTICES " + std::to_string(get_total()) + " " + std::to_string(get_total() * 2) + "\n";
incardon's avatar
incardon committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

		// return the vertex properties string
		return v_out;
	}

	/*! \brief It get the vertex properties list
	 *
	 * It get the vertex properties list of the vertex defined as a VTK header
	 *
	 * \return a string that define the vertex properties in graphML format
	 *
	 */

	std::string get_point_properties_list()
	{
		//! vertex property output string
		std::string v_out;

		// write the number of vertex
		v_out += "POINTS " + std::to_string(get_total()) + " float" + "\n";

		// return the vertex properties string
		return v_out;
	}

	/*! \brief Create the VTK point definition
	 *
	 */
216
	std::string get_point_list()
incardon's avatar
incardon committed
217 218 219 220 221 222
	{
		//! vertex node output string
		std::stringstream v_out;

		//! For each defined grid

Pietro Incardona's avatar
Pietro Incardona committed
223
		for (size_t i = 0 ; i < vps.size() ; i++)
incardon's avatar
incardon committed
224
		{
Pietro Incardona's avatar
Pietro Incardona committed
225 226
			//! write the particle position
			auto it = vps.get(i).g.getIterator();
incardon's avatar
incardon committed
227 228 229 230

			// if there is the next element
			while (it.isNext())
			{
Pietro Incardona's avatar
Pietro Incardona committed
231 232
				Point<pair::first::value_type::dims,typename pair::first::value_type::coord_type> p;
				p = vps.get(i).g.get(it.get());
incardon's avatar
incardon committed
233

Pietro Incardona's avatar
Pietro Incardona committed
234
				if (pair::first::value_type::dims == 2)
incardon's avatar
incardon committed
235 236 237
					v_out << p.toString() << " 0.0" << "\n";
				else
					v_out << p.toString() << "\n";
incardon's avatar
incardon committed
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

				// increment the iterator and counter
				++it;
			}
		}

		// return the vertex list
		return v_out.str();
	}

	/*! \brief Create the VTK vertex definition
	 *
	 */
	std::string get_vertex_list()
	{
		//! vertex node output string
		std::string v_out;

		size_t k = 0;

Pietro Incardona's avatar
Pietro Incardona committed
258
		for (size_t i = 0 ; i < vps.size() ; i++)
incardon's avatar
incardon committed
259 260
		{
			//! For each grid point create a vertex
Pietro Incardona's avatar
Pietro Incardona committed
261
			auto it = vps.get(i).g.getIterator();
incardon's avatar
incardon committed
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298

			while (it.isNext())
			{
				v_out += "1 " + std::to_string(k) + "\n";

				++k;
				++it;
			}
		}
		// return the vertex list
		return v_out;
	}

	/*! \brief Get the point data header
	 *
	 * \return a string with the point data header for VTK format
	 *
	 */
	std::string get_point_data_header()
	{
		std::string v_out;

		v_out += "POINT_DATA " + std::to_string(get_total()) + "\n";

		return v_out;
	}

public:

	/*!
	 *
	 * VTKWriter constructor
	 *
	 */
	VTKWriter()
	{}

Pietro Incardona's avatar
Pietro Incardona committed
299
	/*! \brief Add a vector dataset
incardon's avatar
incardon committed
300
	 *
Pietro Incardona's avatar
Pietro Incardona committed
301 302
	 * \param vps vector of positions
	 * \param vpp vector of properties
303
	 * \param mark additional information that divide the dataset into 2
Pietro Incardona's avatar
Pietro Incardona committed
304
	 *        (in general is used to mark real from ghost information)
incardon's avatar
incardon committed
305 306
	 *
	 */
Pietro Incardona's avatar
Pietro Incardona committed
307
	void add(const typename pair::first & vps, const typename pair::second & vpp,size_t mark)
incardon's avatar
incardon committed
308
	{
Pietro Incardona's avatar
Pietro Incardona committed
309 310
		ele_vps<typename pair::first> t1(vps,mark);
		ele_vpp<typename pair::second> t2(vpp,mark);
incardon's avatar
incardon committed
311

Pietro Incardona's avatar
Pietro Incardona committed
312 313
		this->vps.add(t1);
		this->vpp.add(t2);
incardon's avatar
incardon committed
314 315
	}

Pietro Incardona's avatar
Pietro Incardona committed
316
	/*! \brief It write a VTK file from a vector of points
incardon's avatar
incardon committed
317 318 319 320
	 *
	 * \tparam prp_out which properties to output [default = -1 (all)]
	 *
	 * \param file path where to write
321 322
	 * \param f_name name of the dataset
	 * \param ft specify if it is a VTK BINARY or ASCII file [default = ASCII]
incardon's avatar
incardon committed
323 324
	 *
	 */
Pietro Incardona's avatar
Pietro Incardona committed
325
	template<int prp = -1> bool write(std::string file, std::string f_name = "points" , file_type ft = file_type::ASCII)
incardon's avatar
incardon committed
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
	{
		// Header for the vtk
		std::string vtk_header;
		// Point list of the VTK
		std::string point_list;
		// Vertex list of the VTK
		std::string vertex_list;
		// Graph header
		std::string vtk_binary_or_ascii;
		// vertex properties header
		std::string point_prop_header;
		// edge properties header
		std::string vertex_prop_header;
		// Data point header
		std::string point_data_header;
		// Data point
		std::string point_data;

		// VTK header
		vtk_header = "# vtk DataFile Version 3.0\n"
				     + f_name + "\n";

		// Choose if binary or ASCII
		if (ft == file_type::ASCII)
		{vtk_header += "ASCII\n";}
		else
		{vtk_header += "BINARY\n";}

		// Data type for graph is DATASET POLYDATA
		vtk_header += "DATASET POLYDATA\n";

		// point properties header
		point_prop_header = get_point_properties_list();

		// Get point list
361
		point_list = get_point_list();
incardon's avatar
incardon committed
362 363 364 365 366 367 368 369 370 371 372 373

		// vertex properties header
		vertex_prop_header = get_vertex_properties_list();

		// Get vertex list
		vertex_list = get_vertex_list();

		// Get the point data header
		point_data_header = get_point_data_header();

		// For each property in the vertex type produce a point data

Pietro Incardona's avatar
Pietro Incardona committed
374
		prop_out_v< ele_vpp<typename pair::second>, typename pair::first::value_type::coord_type> pp(point_data, vpp);
incardon's avatar
incardon committed
375 376

		if (prp == -1)
Pietro Incardona's avatar
Pietro Incardona committed
377
			boost::mpl::for_each< boost::mpl::range_c<int,0, pair::second::value_type::max_prop> >(pp);
incardon's avatar
incardon committed
378 379 380
		else
			boost::mpl::for_each< boost::mpl::range_c<int,prp, prp> >(pp);

incardon's avatar
incardon committed
381 382 383 384
		// Add the last property
		pp.lastProp();


incardon's avatar
incardon committed
385 386 387 388 389
		// write the file
		std::ofstream ofs(file);

		// Check if the file is open
		if (ofs.is_open() == false)
incardon's avatar
incardon committed
390
		{std::cerr << "Error cannot create the VTK file: " + file + "\n";}
incardon's avatar
incardon committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404

		ofs << vtk_header << point_prop_header << point_list <<
				vertex_prop_header << vertex_list << point_data_header << point_data;

		// Close the file

		ofs.close();

		// Completed succefully
		return true;
	}
};


Pietro Incardona's avatar
Pietro Incardona committed
405
#endif /* OPENFPM_IO_SRC_VTKWRITER_POINT_SET_HPP_ */