mesh_vtk_file.cpp 80.6 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1 2 3 4 5 6
#ifdef _MSC_VER //kill some warnings
#define _CRT_SECURE_NO_WARNINGS
#endif


#include "inmost.h"
Kirill Terekhov's avatar
Kirill Terekhov committed
7
#include <cfloat>
Kirill Terekhov's avatar
Kirill Terekhov committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

#if defined(USE_MESH)

//vtk states

#define R_VERSION     0
#define R_USERDATA    1
#define R_DATATYPE    2
#define R_WAITDATA    3

#define R_SGRID       4
#define R_RGRID       5
#define R_UGRID       6
#define R_POLYDATA    7
#define R_FIELD       8
#define R_SPOINTS     9

#define R_ATTRIBUTES  10
#define R_ATTRDATA    11

#define R_QUIT		  100

30
//static int __isnan__(double x) { return x != x; }
31
//static int isinf(double x) { return !isnan(x) && isnan(x - x); }
32 33
//static int __isinf__(double x) { return fabs(x) > DBL_MAX; }
//static int __isbad(double x) { return __isnan__(x) || __isinf__(x); }
Kirill Terekhov's avatar
Kirill Terekhov committed
34

35 36


Kirill Terekhov's avatar
Kirill Terekhov committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
template<typename T>
void ReadCoords(FILE * f,INMOST_DATA_REAL_TYPE c[3])
{
	T temp[3];
	if( fread(temp,sizeof(T),3,f) == 3 )
	{
		c[0] = temp[0];
		c[1] = temp[1];
		c[2] = temp[2];
	}
	else 
	{
		std::cout << __FILE__ << ":" << __LINE__ << " Cannot read 3 coordinates from file " << std::endl;
		throw INMOST::BadFile;
	}
}

namespace INMOST
{
56

57 58 59 60 61 62

	void skip_empty(char * readline,FILE * f)
	{
		bool empty = true;
		do
		{
63
			for(size_t k = 0; k < strlen(readline); ++k)
64 65 66 67 68 69 70 71 72 73 74 75 76
				if( !isspace(readline[k]) ) empty = false;
			if( empty )
			{
				if( fgets(readline,2048,f) == NULL ) 
					break;
			}
		} while(empty);
		
	}

	void skip_metadata(int comps, char * readline,FILE * f)
	{
		int dcnt,filled, scnt;
77
		//char ntype[256];
78 79 80 81 82 83 84 85 86 87 88 89 90
		if( !strncmp(readline,"METADATA",8) )
		{
			for(int k = 0; k < 2; ++k)
			{
				if( fgets(readline,2048,f) == NULL ) throw BadFile;
				if( !strncmp(readline,"INFORMATION",11) )
				{
					filled = sscanf(readline,"%*s %d",&dcnt); //INFORMATION %d
					if( filled != 1 ) throw BadFile;
					for(int k = 0; k < dcnt; ++k) //2 lines per data
					{
						if( fgets(readline,2048,f) == NULL )  //NAME
							throw BadFile;
91
						filled = fscanf(f,"%*s"); //DATA
92 93
						filled = fscanf(f,"%d",&scnt); //vector size
						if( filled != 1 ) throw BadFile;
94
						for(int q = 0; q < scnt; ++q) filled = fscanf(f,"%*s\n");
95 96 97 98 99 100 101 102 103 104 105 106 107 108
					}
				}
				else if( !strncmp(readline,"COMPONENT_NAMES",15) )
				{
					for(int k = 0; k < comps; ++k) //2 lines per data
					{
						if( fgets(readline,2048,f) == NULL ) 
							throw BadFile;
					}
				}
			}
		}
	}

109 110 111 112 113 114 115 116 117
	std::string Space2Underscore(const std::string & inp)
	{
		std::string ret = inp;
		for (size_t k = 0; k < ret.size(); ++k)
		{
			if (ret[k] == ' ') ret[k] = '_';
		}
		return ret;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
118 119 120 121 122
  
	int VtkElementType(ElementType t)
	{
		switch(t)
		{
123
			case Element::Line: return 3;
Kirill Terekhov's avatar
Kirill Terekhov committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
			case Element::Tri: return 5;
			case Element::Quad: return 9;
			case Element::MultiLine: return 4;
			case Element::Polygon: return 7;
			case Element::Tet: return 10;
			case Element::Hex: return 12;
			case Element::Prism: return 13;
			case Element::Pyramid: return 14;
			case Element::Polyhedron: return 42;
			case Element::MultiPolygon: return 42;
		}
		assert(false);
		return -1;
	}
	
	INMOST_DATA_ENUM_TYPE VtkElementNodes(ElementType t)
	{
		switch(t)
		{
143
			case Element::Line: return 2;
Kirill Terekhov's avatar
Kirill Terekhov committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
			case Element::Tri: return 3;
			case Element::Quad: return 4;
			case Element::MultiLine: return ENUMUNDEF;
			case Element::Polygon: return ENUMUNDEF;
			case Element::Tet: return 4;
			case Element::Hex: return 8;
			case Element::Prism: return 6;
			case Element::Pyramid: return 5;
			case Element::Polyhedron: return ENUMUNDEF;
			case Element::MultiPolygon: return ENUMUNDEF;
		}
		assert(false);
		return ENUMUNDEF;
	}
	

  void Mesh::SaveVTK(std::string File)
  {
		integer dim = GetDimensions();
		if( dim > 3 )
		{
165
			std::cout << "VTK file supports 3 dimensions max" << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
166 167
			return;
		}
168 169 170 171 172 173 174 175 176
		std::ofstream f(File.c_str());
		//~ FILE * f = fopen(File.c_str(),"w");
		//~ if( !f ) throw BadFileName;
		if( f.fail() ) throw BadFileName;
		f << "# vtk DataFile Version 3.0\n";
		if (this->GetFileOption("VTK_OUTPUT_FACES") == "1") f << "VTK_OUTPUT_FACES file is written by INMOST\n";
		else f << "file is written by INMOST\n";
		f << "ASCII\n";
		f << "DATASET UNSTRUCTURED_GRID\n";
177 178 179 180 181 182 183 184 185

		bool output_faces = false;
		for (INMOST_DATA_ENUM_TYPE k = 0; k < file_options.size(); ++k)
		{
			if (file_options[k].first == "VTK_OUTPUT_FACES")
			{
				output_faces = true;
			}
		}
186 187 188 189 190 191
		
		std::set< std::string > nosave, saveonly;
		
		nosave = TagOptions("nosave");
		saveonly = TagOptions("saveonly");
		
Kirill Terekhov's avatar
Kirill Terekhov committed
192
		//ReorderEmpty(CELL | NODE);
193
		Tag set_id = CreateTag("TEMPORARY_ELEMENT_ID",DATA_INTEGER,CELL |FACE| NODE,NONE,1);
Kirill Terekhov's avatar
Kirill Terekhov committed
194 195 196 197
		Storage::integer cur_num = 0;
		for(Mesh::iteratorNode it = BeginNode(); it != EndNode(); ++it) it->IntegerDF(set_id) = cur_num++;
		cur_num = 0;
		for(Mesh::iteratorCell it = BeginCell(); it != EndCell(); ++it) it->IntegerDF(set_id) = cur_num++;
198
		cur_num = 0;
199 200 201

		if (output_faces) for (Mesh::iteratorFace it = BeginFace(); it != EndFace(); ++it) it->IntegerDF(set_id) = cur_num++;

202
		f << "POINTS " << NumberOfNodes() << " double\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
203 204 205 206 207 208
		for(Mesh::iteratorNode it = BeginNode(); it != EndNode(); it++)
		{
			Storage::real_array coords = it->RealArray(CoordsTag());
			for(integer i = 0; i < dim; i++) 
			{
				double temp = coords[i];
209
				f << temp << " ";
Kirill Terekhov's avatar
Kirill Terekhov committed
210 211
			}
			for(integer i = dim; i < 3; i++)
212 213
				f << "0 ";
			f << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
214 215
		}
		{
216
			std::vector<int> values;
Kirill Terekhov's avatar
Kirill Terekhov committed
217 218 219 220 221 222
			for(Mesh::iteratorCell it = BeginCell(); it != EndCell(); it++)
			{	
				switch(it->GetGeometricType())
				{
					case Element::Tri:
					case Element::Quad:
223 224
					//case Element::MultiLine:
					//case Element::Polygon:
Kirill Terekhov's avatar
Kirill Terekhov committed
225
					case Element::Tet:
226 227 228
					case Element::Hex:
					case Element::Pyramid:
					case Element::Prism:
Kirill Terekhov's avatar
Kirill Terekhov committed
229
					{
230 231
						ElementArray<Node> nodes(this);// = it->getNodes();
						RestoreCellNodes(*it,nodes);
Kirill Terekhov's avatar
Kirill Terekhov committed
232
						if( nodes.size() != VtkElementNodes(it->GetGeometricType()) ) goto safe_output;
Kirill Terekhov's avatar
Kirill Terekhov committed
233 234 235 236
						values.push_back(static_cast<integer>(nodes.size()));
						for(ElementArray<Node>::iterator jt = nodes.begin(); jt != nodes.end(); jt++)
							values.push_back(jt->IntegerDF(set_id));
						break;
237 238 239 240 241 242 243 244 245
					}
					case Element::MultiLine:
					case Element::Polygon:
					{
						ElementArray<Node> nodes = it->getNodes();
						values.push_back(static_cast<integer>(nodes.size()));
						for(ElementArray<Node>::iterator jt = nodes.begin(); jt != nodes.end(); jt++)
							values.push_back(jt->IntegerDF(set_id));
						break;
Kirill Terekhov's avatar
Kirill Terekhov committed
246 247 248 249 250
					}
					case Element::Polyhedron:
					case Element::MultiPolygon:
					{
safe_output:
251
						
Kirill Terekhov's avatar
Kirill Terekhov committed
252
						ElementArray<Face> faces = it->getFaces();
Kirill Terekhov's avatar
Kirill Terekhov committed
253 254 255 256
						integer totalNum = 1 + static_cast<integer>(faces.size());
                        for(ElementArray<Face>::iterator jt = faces.begin(); jt != faces.end(); jt++)
							totalNum += jt->nbAdjElements(NODE);
						values.push_back(totalNum);
Kirill Terekhov's avatar
Kirill Terekhov committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270
						values.push_back(static_cast<integer>(faces.size()));
						for(ElementArray<Face>::iterator jt = faces.begin(); jt != faces.end(); jt++)
						{
							ElementArray<Node> nodes = jt->getNodes();
							values.push_back(static_cast<integer>(nodes.size()));
							if( jt->FaceOrientedOutside(it->self()) )
								for(ElementArray<Node>::iterator kt = nodes.begin(); kt != nodes.end(); kt++)
									values.push_back(kt->IntegerDF(set_id));
							else
								for(ElementArray<Node>::reverse_iterator kt = nodes.rbegin(); kt != nodes.rend(); kt++)
									values.push_back(kt->IntegerDF(set_id));
						}
						break;
					}
271
					default: std::cout << __FILE__ << ":" << __LINE__ << " This should not happen " << Element::GeometricTypeName(it->GetGeometricType()) << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
272 273
				}
			}
274
			if (output_faces)
275
			{
276
				for (Mesh::iteratorFace it = BeginFace(); it != EndFace(); it++)
277
				{
278 279 280 281
					switch (it->GetGeometricType())
					{
					case Element::Line:
					{
282 283 284 285 286
						ElementArray<Node> nodes = it->getNodes();
						values.push_back(static_cast<integer>(nodes.size()));
						for (ElementArray<Node>::iterator jt = nodes.begin(); jt != nodes.end(); jt++)
							values.push_back(jt->IntegerDF(set_id));
						break;
287 288 289 290 291 292
					}
					case Element::Tri:
					case Element::Quad:
					case Element::MultiLine:
					case Element::Polygon:
					{
293 294 295 296 297
						ElementArray<Node> nodes = it->getNodes();
						values.push_back(static_cast<integer>(nodes.size()));
						for (ElementArray<Node>::iterator jt = nodes.begin(); jt != nodes.end(); jt++)
							values.push_back(jt->IntegerDF(set_id));
						break;
298
					}
299
					default: std::cout << __FILE__ << ":" << __LINE__ << " This should not happen " << Element::GeometricTypeName(it->GetGeometricType()) << std::endl;
300
					}
301
				}
302
				f << "CELLS " << NumberOfCells() + NumberOfFaces() << " " << values.size() << "\n";
303
			}
304
			else
305
				f << "CELLS " << NumberOfCells() << " " << values.size() << "\n";
306

307
			for(size_t i = 0; i < values.size(); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
308
			{
309 310
				f << values[i] << " ";
				if( (i+1) % 20 == 0) f << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
311
			}
312
			f << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
313
		}
314
		if (output_faces)
315
			f << "CELL_TYPES " << NumberOfCells() + NumberOfFaces() << "\n";
316
		else 			
317
			f << "CELL_TYPES " << NumberOfCells() << "\n";
318

Kirill Terekhov's avatar
Kirill Terekhov committed
319 320 321 322
		for(Mesh::iteratorCell it = BeginCell(); it != EndCell(); it++)
		{
			INMOST_DATA_ENUM_TYPE nnodes = VtkElementNodes(it->GetGeometricType());
			if( nnodes == ENUMUNDEF || nnodes == it->nbAdjElements(NODE) ) //nodes match - output correct type
323
				f << VtkElementType(it->GetGeometricType()) << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
324
			else //number of nodes mismatch with expected - some topology checks must be off
325
				f << VtkElementType(Element::MultiPolygon) << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
326
		}
327 328 329 330 331
		if (output_faces){
			for (Mesh::iteratorFace it = BeginFace(); it != EndFace(); it++)
			{
				INMOST_DATA_ENUM_TYPE nnodes = VtkElementNodes(it->GetGeometricType());
				if (nnodes == ENUMUNDEF || nnodes == it->nbAdjElements(NODE)) //nodes match - output correct type
332
					f << VtkElementType(it->GetGeometricType()) << "\n";
333
				else //number of nodes mismatch with expected - some topology checks must be off
334
					f << VtkElementType(Element::MultiPolygon) << "\n";
335
			}
336
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
337 338 339 340 341 342 343 344
		DeleteTag(set_id);
		{
			std::vector<std::string> tag_names;
			std::vector<Tag> tags;
			ListTagNames(tag_names);
			for(unsigned int i = 0; i < tag_names.size(); i++)
			{
				Tag t = GetTag(tag_names[i]);
345
				if (((t.isDefined(CELL) /*&& !t.isSparse(CELL)*/)
346
					|| (t.isDefined(FACE) && output_faces)) &&
347 348 349 350 351 352 353 354
						t.GetPrint() && //Temporary solution: @see Mesh::file_option
						t.GetDataType() != DATA_BULK && 
						t.GetDataType() != DATA_REFERENCE &&
						t.GetDataType() != DATA_REMOTE_REFERENCE &&
						t != CoordsTag() && 
						t != SharedTag() && 
						t != SendtoTag() && 
						t != ProcessorsTag())
Kirill Terekhov's avatar
Kirill Terekhov committed
355
				{
356 357 358
					bool skip = CheckSaveSkip(tag_names[i],nosave,saveonly);
					if( !skip )
						tags.push_back(t);
Kirill Terekhov's avatar
Kirill Terekhov committed
359 360 361
				}
			}
				
362 363
			if (!tags.empty() && output_faces) 
			{ 
364
				f << "CELL_DATA " << NumberOfCells() + NumberOfFaces() << "\n"; 
365
			}
366
			else if (!tags.empty()) f << "CELL_DATA " << NumberOfCells() << "\n";
367

368
			for(INMOST_DATA_ENUM_TYPE i = 0; i < tags.size(); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
369
			{
370
				INMOST_DATA_ENUM_TYPE comps = tags[i].GetSize();
Kirill Terekhov's avatar
Kirill Terekhov committed
371 372 373 374 375
				if( comps == ENUMUNDEF )
					continue;
				else
				{
					{
376 377
						std::string type_str = "int";
						if(  tags[i].GetDataType() == DATA_REAL
Kirill Terekhov's avatar
Kirill Terekhov committed
378
#if defined(USE_AUTODIFF)
379
						   || tags[i].GetDataType() == DATA_VARIABLE
Kirill Terekhov's avatar
Kirill Terekhov committed
380
#endif
381
						   ) type_str = "double";
382 383
						f << "SCALARS " << Space2Underscore(tags[i].GetTagName()) << " " << type_str << " " << comps << "\n";
						f << "LOOKUP_TABLE default\n";
384
						for (Mesh::iteratorCell it = BeginCell(); it != EndCell(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
385
						{
386 387 388 389
							switch (tags[i].GetDataType())
							{
							case DATA_REAL:
							{
390 391 392 393 394 395
								if (tags[i].isDefined(CELL) && it->HaveData(tags[i]))
								{
									Storage::real_array arr = it->RealArray(tags[i]);
									for (unsigned int m = 0; m < comps; m++)
									{
										double val = static_cast<double>(arr[m]);
396
										f << (__isbad(val) ? -0.9999E30 : val) << " ";
397 398
									}
								}
399 400
								else for (unsigned int m = 0; m < comps; m++) f << -0.9999E30 << " ";
								f << "\n";
401
							}
402
							break;
403
							case DATA_INTEGER:
Kirill Terekhov's avatar
Kirill Terekhov committed
404
							{
405 406 407
								if (tags[i].isDefined(CELL) && it->HaveData(tags[i]))
								{
									Storage::integer_array arr = it->IntegerArray(tags[i]);
408
									for (unsigned int m = 0; m < comps; m++) f << arr[m] << " ";
409
								}
410 411
								else for (unsigned int m = 0; m < comps; m++) f << INT_MIN << " ";
								f << "\n";
412
							}
413
							break;
414 415 416
#if defined(USE_AUTODIFF)
							case DATA_VARIABLE:
							{
417 418 419 420 421 422
								if (tags[i].isDefined(CELL) && it->HaveData(tags[i]))
								{
									Storage::var_array arr = it->VariableArray(tags[i]);
									for (unsigned int m = 0; m < comps; m++)
									{
										double val = static_cast<double>(arr[m].GetValue());
423
										f << (__isbad(val) ? -0.9999E30 : val) << " ";
424 425
									}
								}
426 427
								else for (unsigned int m = 0; m < comps; m++) f << -0.9999E30 << " ";
								f << "\n";
428
							}
429
							break;
430 431 432 433 434
#endif
							default: continue;
							}
						}
							
435 436


437 438
						if (output_faces)
						{
439 440 441 442 443 444
							for (Mesh::iteratorFace it = BeginFace(); it != EndFace(); it++)
							{
								switch (tags[i].GetDataType())
								{
								case DATA_REAL:
								{
445 446 447
									if (tags[i].isDefined(FACE) && it->HaveData(tags[i]))
									{
										Storage::real_array arr = it->RealArray(tags[i]);
448
										for (unsigned int m = 0; m < comps; m++) f << arr[m] << " ";
449
									}
450 451
									else for (unsigned int m = 0; m < comps; m++) f << -0.9999E30 << " ";
									f << "\n";
452
								}
453
								break;
454 455
								case DATA_INTEGER:
								{
456 457 458
									if (tags[i].isDefined(FACE) && it->HaveData(tags[i]))
									{
										Storage::integer_array arr = it->IntegerArray(tags[i]);
459
										for (unsigned int m = 0; m < comps; m++) f << arr[m] << " ";
460
									}
461 462
									else for (unsigned int m = 0; m < comps; m++) f << INT_MIN << " ";
									f << "\n";
463
								}
464
								break;
Kirill Terekhov's avatar
Kirill Terekhov committed
465
#if defined(USE_AUTODIFF)
466 467
								case DATA_VARIABLE:
								{
468 469 470 471 472 473
									if (tags[i].isDefined(FACE) && it->HaveData(tags[i]))
									{
										Storage::var_array arr = it->VariableArray(tags[i]);
										for (unsigned int m = 0; m < comps; m++)
										{
											double val = static_cast<double>(arr[m].GetValue());
474
											f << (__isbad(val) ? -0.9999E30 : val) << " ";
475 476
										}
									}
477 478
									else for (unsigned int m = 0; m < comps; m++) f << -0.9999E30 << " ";
									f << "\n";
479
								}
480
								break;
Kirill Terekhov's avatar
Kirill Terekhov committed
481
#endif
482 483
								default: continue;
								}
Kirill Terekhov's avatar
Kirill Terekhov committed
484 485 486 487 488 489 490 491 492 493 494 495 496
							}
						}
					}
				}
			}
		}
		{
			std::vector<std::string> tag_names;
			std::vector<Tag> tags;
			ListTagNames(tag_names);
			for(unsigned int i = 0; i < tag_names.size(); i++)
			{
				Tag t = GetTag(tag_names[i]);
497 498 499 500 501 502 503 504
				if( t.isDefined(NODE) && /*!t.isSparse(NODE) &&*/
				    t.GetDataType() != DATA_BULK &&
				    t.GetDataType() != DATA_REFERENCE &&
				    t.GetDataType() != DATA_REMOTE_REFERENCE &&
					t != CoordsTag() &&
				    t != SharedTag() &&
				    t != SendtoTag() &&
				    t != ProcessorsTag())
Kirill Terekhov's avatar
Kirill Terekhov committed
505 506 507
					tags.push_back(t);
			}
				
508 509
			if( !tags.empty() ) f << "POINT_DATA " << NumberOfNodes() << "\n";
			for(INMOST_DATA_ENUM_TYPE i = 0; i < tags.size(); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
510
			{
511
				INMOST_DATA_ENUM_TYPE comps = tags[i].GetSize();
Kirill Terekhov's avatar
Kirill Terekhov committed
512 513 514 515 516
				if( comps == ENUMUNDEF )
					continue;
				else
				{
					{
517 518
						std::string type_str = "int";
						if(  tags[i].GetDataType() == DATA_REAL
Kirill Terekhov's avatar
Kirill Terekhov committed
519
#if defined(USE_AUTODIFF)
520
						   || tags[i].GetDataType() == DATA_VARIABLE
Kirill Terekhov's avatar
Kirill Terekhov committed
521
#endif
522
						   ) type_str = "double";
523 524
						f << "SCALARS " << Space2Underscore(tags[i].GetTagName()) << " " << type_str << " " << comps << "\n";
						f << "LOOKUP_TABLE default\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
525 526 527 528 529 530
						for(Mesh::iteratorNode it = BeginNode(); it != EndNode(); it++)
						{
							switch( tags[i].GetDataType() )
							{
								case DATA_REAL:
								{
531
									if (it->HaveData(tags[i]))
Kirill Terekhov's avatar
Kirill Terekhov committed
532
									{
533 534 535 536
										Storage::real_array arr = it->RealArray(tags[i]);
										for(unsigned int m = 0; m < comps; m++)
										{
											double val = static_cast<double>(arr[m]);
537
											f << (__isbad(val) ? -0.9999E30 : val) << " ";
538
										}
539
										f << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
540
									}
541
									else for(unsigned int m = 0; m < comps; m++) f << -0.9999E30 << " ";
Kirill Terekhov's avatar
Kirill Terekhov committed
542 543 544 545
								}
								break;
								case DATA_INTEGER:
								{
546 547 548
									if (it->HaveData(tags[i]))
									{
										Storage::integer_array arr = it->IntegerArray(tags[i]);
549 550
										for(unsigned int m = 0; m < comps; m++) f << arr[m] << " ";
										f << "\n";
551
									}
552
									else for (unsigned int m = 0; m < comps; m++) f << INT_MIN << " ";
Kirill Terekhov's avatar
Kirill Terekhov committed
553 554
								}
								break;
Kirill Terekhov's avatar
Kirill Terekhov committed
555
#if defined(USE_AUTODIFF)
556
								case DATA_VARIABLE:
Kirill Terekhov's avatar
Kirill Terekhov committed
557
								{
558
									if (it->HaveData(tags[i]))
Kirill Terekhov's avatar
Kirill Terekhov committed
559
									{
560 561 562 563
										Storage::var_array arr = it->VariableArray(tags[i]);
										for(unsigned int m = 0; m < comps; m++)
										{
											double val = static_cast<double>(arr[m].GetValue());
564
											f << (__isbad(val) ? -0.9999E30 : val) << " ";
565
										}
566
										f << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
567
									}
568
									else for(unsigned int m = 0; m < comps; m++) f << -0.9999E30 << " ";
Kirill Terekhov's avatar
Kirill Terekhov committed
569 570 571
								}
								break;
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
572 573 574 575 576 577 578 579 580
								default: continue;
							}
						}
					}
				}
			}
		}
	}

581 582 583
	void Mesh::LoadVTK(std::string File)
	{
		int verbosity = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
584 585 586 587 588 589 590
		for(INMOST_DATA_ENUM_TYPE k = 0; k < file_options.size(); ++k)
		{
			if( file_options[k].first == "VERBOSITY" )
			{
				verbosity = atoi(file_options[k].second.c_str());
				if( verbosity < 0 || verbosity > 2 )
				{
591
					std::cout << __FILE__ << ":" << __LINE__ << " Unknown verbosity option: " << file_options[k].second << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
592 593 594 595
					verbosity = 1;
				}
			}
		}
596 597 598 599 600 601
		
		std::set< std::string > noload, loadonly;
		
		noload = TagOptions("noload");
		loadonly = TagOptions("loadonly");
		
Kirill Terekhov's avatar
Kirill Terekhov committed
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659

		MarkerType unused_marker = CreateMarker();
		int grid_is_2d = 2;
		for(INMOST_DATA_ENUM_TYPE k = 0; k < file_options.size(); ++k)
		{
			if( file_options[k].first == "VTK_GRID_DIMS" )
			{
				if( file_options[k].second == "AUTO" )
					grid_is_2d = 2;
				if( atoi(file_options[k].second.c_str()) == 2 )
					grid_is_2d = 1;
				else if( atoi(file_options[k].second.c_str()) == 3 )
					grid_is_2d = 0;
			}
		}

		//Determine whether there are already 3d elements so that the grid is 3d
		if( grid_is_2d == 2 && NumberOfCells() )
		{
			for(Mesh::iteratorCell it = BeginCell(); it != EndCell() && grid_is_2d == 2; ++it)
				if( it->GetElementDimension() == 3 )
					grid_is_2d = 0;
		}


		std::vector<HandleType> old_nodes(NumberOfNodes());
		{
			unsigned qq = 0;
			for(Mesh::iteratorNode it = BeginNode(); it != EndNode(); ++it)
				old_nodes[qq++] = *it;
		}
		if( !old_nodes.empty() ) 
		{
			std::sort(old_nodes.begin(),old_nodes.end(),CentroidComparator(this));
			//for(std::vector<HandleType>::iterator it = old_nodes.begin(); it != old_nodes.end(); ++it)
			//{
			//	Storage::real_array c = RealArrayDF(*it,CoordsTag());
			//	REPORT_VAL("coord: ",c[0] << " " << c[1] << " " << c[2]);
			//}
		}

			
		FILE * f = fopen(File.c_str(),"r");
		if( !f ) 
		{
			std::cout << __FILE__ << ":" << __LINE__ << " cannot open " << File << std::endl;
			throw BadFileName;
		}
		std::vector<Tag> datatags;
		std::vector<HandleType> newnodes;
		std::vector<HandleType> newcells;
		std::vector<int> cp;
		std::vector<int> ct;
		unsigned int state = R_VERSION;
		char readline[2048];
		int filled;
		bool binary = false;
		int read_into = NONE, read_into_cell = NONE;
660
		bool read_next_line = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
661 662
		while( state != R_QUIT )
		{
663 664
			
			if( read_next_line )
Kirill Terekhov's avatar
Kirill Terekhov committed
665
			{
666 667 668 669 670 671
				if( fgets(readline,2048,f) == NULL )
				{
					state = R_QUIT;
					continue;
				}
			} else read_next_line = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
672 673 674
			//if( readline[strlen(readline)-1] == '\n' )
			//	readline[strlen(readline)-1] = '\0';
			while( strlen(readline) != 0 && isspace(readline[strlen(readline)-1]) )
Kirill Terekhov's avatar
Kirill Terekhov committed
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
				readline[strlen(readline)-1] = '\0';
			if( strlen(readline) == 0 ) continue;
			switch( state )
			{
				case R_VERSION:
				{
					int h,l;
					filled = sscanf(readline,"# vtk DataFile Version %1d.%1d",&h,&l);
					if( filled == 0 ) 
					{
						std::cout << __FILE__ << ":" << __LINE__ << " version information not found in " << File << std::endl;
						throw BadFile;
					}
					//file version checker
					state = R_USERDATA;
					break;
				}
				case R_USERDATA:
				{
694
					if (!strncmp(readline, "VTK_OUTPUT_FACES", 16)) this->SetFileOption("VTK_OUTPUT_FACES", "1");
Kirill Terekhov's avatar
Kirill Terekhov committed
695 696 697 698 699 700
					state = R_DATATYPE;
					break;
				}
				case R_DATATYPE:
				{
					if( !strncmp(readline,"BINARY",6) )
Kirill Terekhov's avatar
Kirill Terekhov committed
701
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
702
						binary = 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
703 704
						state = R_WAITDATA;
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
					else if( !strncmp(readline,"ASCII",5) )
						state = R_WAITDATA;
					else 
					{
						std::cout << __FILE__ << ":" << __LINE__ << " unexpected data type " << readline << " in " << File << " expected BINARY or ASCII instead " << std::endl;
						throw BadFile;
					}
					break;
				}
				case R_ATTRDATA:
				{
					char dataname[1024];
					char attrname[1024];
					char attrtype[1024];
					int nentries = 1;
					filled = sscanf(readline," %s ",dataname);
					if( filled != 1 ) 
					{
						std::cout << __FILE__ << ":" << __LINE__ << " cannot read attribute name in " << File << std::endl;
						throw BadFile;
					}
					if( !strcmp(dataname,"SCALARS") )
					{
						DataType t = DATA_BULK;
						filled = sscanf(readline," SCALARS %s %s %d",attrname,attrtype,&nentries);
730
						bool skip = CheckLoadSkip(attrname,noload,loadonly);
731
						if( verbosity > 0 ) std::cout << (skip?"Skipping":"Reading") << " scalar attribute " << attrname << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
732 733
						if( filled < 2 ) 
						{
734
							std::cout << __FILE__ << ":" << __LINE__ << " found " << filled << " arguments to SCALARS field, must be >= 2\nline:\n" << readline << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
735 736 737 738 739 740 741 742 743 744 745
							throw BadFile;
						}
						for(unsigned int i = 0; i < strlen(attrtype); i++) attrtype[i] = tolower(attrtype[i]);
						if( !strcmp(attrtype,"bit") || !strcmp(attrtype,"unsigned_char") || !strcmp(attrtype,"char") ||
							  !strcmp(attrtype,"unsigned_short") || !strcmp(attrtype,"short") || !strcmp(attrtype,"unsigned_int") ||
							  !strcmp(attrtype,"int") || !strcmp(attrtype,"unsigned_long") || !strcmp(attrtype,"long"))
							t = DATA_INTEGER;
						else if( !strcmp(attrtype,"float") || !strcmp(attrtype,"double") )
							t = DATA_REAL;
						else
						{
746
							std::cout << __FILE__ << ":" << __LINE__ << " unexpected data type " << attrtype << " in " << File << " for " << attrname << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
747 748 749 750 751 752 753 754 755 756
							std::cout << "expected one of: bit, unsigned_char, char, unsigned_short, short, unsigned_int, int, unsigned_long, long, float, double" << std::endl;
							throw BadFile;
						}
						if( fgets(readline,2048,f) == NULL ) 
						{
							std::cout << __FILE__ << ":" << __LINE__ << " expected LOOKUP_TABLE in " << File << std::endl;
							throw BadFile; //LOOK_UP TABLE
						}
						if( read_into == 2 )
						{
757
							bool sparse = (std::string(attrname).substr(0,9) != "PROTECTED");
Kirill Terekhov's avatar
Kirill Terekhov committed
758
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newcells.size()/250),1);
759
							if( skip )
Kirill Terekhov's avatar
Kirill Terekhov committed
760
							{
761
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
762
								{
763 764 765 766 767 768

									if( t == DATA_INTEGER )
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile;}
									if( t == DATA_REAL )
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; }
									if( verbosity > 1 && it%report_pace == 0)
Kirill Terekhov's avatar
Kirill Terekhov committed
769
									{
770 771 772 773
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
Kirill Terekhov's avatar
Kirill Terekhov committed
774 775
									}
								}
776 777 778 779 780
							}
							else
							{
								Tag attr = CreateTag(attrname,t,read_into_cell,sparse ? read_into_cell & ~CELL : NONE,nentries);
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
781
								{
782 783

									if( t == DATA_INTEGER )
Kirill Terekhov's avatar
Kirill Terekhov committed
784
									{
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
										if( newcells[it] != InvalidHandle() )
										{
											Storage::integer_array attrdata = IntegerArray(newcells[it],attr);
											for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
										}
										else for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile;}
									}
									if( t == DATA_REAL )
									{
										if( newcells[it] != InvalidHandle() )
										{
											Storage::real_array attrdata = RealArray(newcells[it],attr);
											for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
										}
										else for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; }
									}
									if( verbosity > 1 && it%report_pace == 0)
									{
803 804 805 806
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
Kirill Terekhov's avatar
Kirill Terekhov committed
807 808
									}
								}
809
								datatags.push_back(attr);
Kirill Terekhov's avatar
Kirill Terekhov committed
810 811 812 813 814
							}
						}
						if( read_into == 1 )
						{
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newnodes.size())/250,1);
815
							if( skip )
Kirill Terekhov's avatar
Kirill Terekhov committed
816
							{
817
								for(unsigned int it = 0; it < newnodes.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
818
								{
819 820 821 822 823 824
									if( t == DATA_INTEGER )
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile;}
									if( t == DATA_REAL )
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
									if( verbosity > 1 && it%report_pace == 0)
									{
825 826 827 828
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newnodes.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
829
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
830
								}
831 832 833 834 835
							}
							else
							{
								Tag attr = CreateTag(attrname,t,NODE,NONE,nentries);
								for(unsigned int it = 0; it < newnodes.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
836
								{
837 838 839 840 841 842 843 844 845 846 847 848
									if( t == DATA_INTEGER )
									{
										Storage::integer_array attrdata = IntegerArray(newnodes[it],attr);
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
									}
									if( t == DATA_REAL )
									{
										Storage::real_array attrdata = RealArray(newnodes[it],attr);
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
									}
									if( verbosity > 1 && it%report_pace == 0)
									{
849 850 851 852
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newnodes.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
853
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
854 855
								}
							}
856
							//filled = fscanf(f,"\n");
Kirill Terekhov's avatar
Kirill Terekhov committed
857
						}
858 859 860 861 862 863
						if( fgets(readline,2048,f) == NULL ) throw BadFile;
						skip_empty(readline,f);
						skip_metadata(3,readline,f);
						skip_empty(readline,f);
						read_next_line = false;
						
Kirill Terekhov's avatar
Kirill Terekhov committed
864 865 866 867 868 869
						break;
					}
					else if( !strcmp(dataname,"COLOR_SCALARS") )
					{	
						char attrname[1024];
						filled = sscanf(readline," COLOR_SCALARS %s %d",attrname,&nentries);
870
						bool skip = CheckLoadSkip(attrname,noload,loadonly);
871
						if( verbosity > 0 ) std::cout << (skip?"Skipping":"Reading") << " color attribute " << attrname << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
872 873
						if( read_into == 2 )
						{
874
							bool sparse = (std::string(attrname).substr(0,9) != "PROTECTED");
Kirill Terekhov's avatar
Kirill Terekhov committed
875
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newcells.size()/250),1);
876
							if( skip )
Kirill Terekhov's avatar
Kirill Terekhov committed
877
							{
878
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
879
								{
880
									for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
881
									if( verbosity > 1 && it%report_pace == 0)
882
									{
883 884 885 886
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
887
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
888
								}
889 890 891 892 893
							}
							else
							{
								Tag attr = CreateTag(attrname,DATA_REAL,read_into_cell,sparse ? read_into_cell & ~CELL : NONE,nentries);
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
894
								{
895 896 897 898 899 900
									if( newcells[it] != InvalidHandle() )
									{
										Storage::real_array attrdata = RealArray(newcells[it],attr);
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
									}
									else for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
901
									if( verbosity > 1 && it%report_pace == 0)
902
									{
903 904 905 906
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
907
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
908
								}
909
								datatags.push_back(attr);
Kirill Terekhov's avatar
Kirill Terekhov committed
910 911 912 913 914
							}
						}
						if( read_into == 1 )
						{
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newnodes.size()/250),1);
915
							if( skip ) 
Kirill Terekhov's avatar
Kirill Terekhov committed
916
							{
917
								for(unsigned int it = 0; it < newnodes.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
918
								{
919 920 921
									for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
									if( verbosity > 1 && it%report_pace == 0)
									{
922 923 924 925
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newnodes.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
926 927 928 929 930 931 932 933 934 935 936 937
									}
								}
							}
							else
							{
								Tag attr = CreateTag(attrname,DATA_REAL,NODE,NONE,nentries);
								for(unsigned int it = 0; it < newnodes.size(); it++)
								{
									Storage::real_array attrdata = RealArray(newnodes[it],attr);
									for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
									if( verbosity > 1 && it%report_pace == 0)
									{
938 939 940 941
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newnodes.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
942
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
943 944
								}
							}
945
							//filled = fscanf(f,"\n");
Kirill Terekhov's avatar
Kirill Terekhov committed
946
						}
947 948 949 950 951 952
						if( fgets(readline,2048,f) == NULL ) throw BadFile;
						skip_empty(readline,f);
						skip_metadata(3,readline,f);
						skip_empty(readline,f);
						read_next_line = false;
					
Kirill Terekhov's avatar
Kirill Terekhov committed
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
						break;
					}
					else if( !strcmp(dataname," LOOKUP_TABLE") )
					{
						int nentries;
						filled = sscanf(readline," LOOKUP_TABLE %*s %d",&nentries);
						if( filled != 1 ) throw BadFile;
						for(int i = 0; i < nentries; i++)
						{
							filled = fscanf(f," %*f %*f %*f %*f");
						}
						filled = fscanf(f,"\n");
						break;
					}
					else if( !strcmp(dataname,"NORMALS") || !strcmp(dataname,"VECTORS") || !strcmp(dataname,"TENSORS"))
					{
						char attrname[1024];
						char attrtype[1024];
						int nentries = 3;
						if( !strcmp(dataname,"TENSORS") ) nentries = 9;
						DataType t = DATA_BULK;
						filled = sscanf(readline,"%*s %s %s",attrname,attrtype);
975
						bool skip = CheckLoadSkip(attrname,noload,loadonly);
976
						if( verbosity > 0 ) std::cout << (skip? "Skipping":"Reading") << " " << dataname << " attribute " << attrname << "n";
Kirill Terekhov's avatar
Kirill Terekhov committed
977 978 979 980 981 982 983 984 985 986 987 988 989
						if( filled != 2 ) throw BadFile;
						for(unsigned int i = 0; i < strlen(attrtype); i++) attrtype[i] = tolower(attrtype[i]);
						if( !strcmp(attrtype,"bit") || !strcmp(attrtype,"unsigned_char") || !strcmp(attrtype,"char") ||
							  !strcmp(attrtype,"unsigned_short") || !strcmp(attrtype,"short") || !strcmp(attrtype,"unsigned_int") ||
							  !strcmp(attrtype,"int") || !strcmp(attrtype,"unsigned_long") || !strcmp(attrtype,"long"))
							t = DATA_INTEGER;
						else if( !strcmp(attrtype,"float") || !strcmp(attrtype,"double") )
							t = DATA_REAL;
						else
							throw BadFile;
						if( fgets(readline,2048,f) == NULL ) throw BadFile; //LOOK_UP TABLE
						if( read_into == 2 )
						{
990
							bool sparse = (std::string(attrname).substr(0,9) != "PROTECTED");
Kirill Terekhov's avatar
Kirill Terekhov committed
991
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newcells.size()/250),1);
992
							if( skip )
Kirill Terekhov's avatar
Kirill Terekhov committed
993
							{
994
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
995
								{
996 997 998 999 1000
									if( t == DATA_INTEGER )
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile;}
									if( t == DATA_REAL )
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
									if( verbosity > 1 && it%report_pace == 0)
Kirill Terekhov's avatar
Kirill Terekhov committed
1001
									{
1002 1003 1004 1005
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
Kirill Terekhov's avatar
Kirill Terekhov committed
1006 1007
									}
								}
1008 1009 1010 1011 1012
							}
							else
							{
								Tag attr = CreateTag(attrname,t,read_into_cell,sparse ? read_into_cell & ~CELL : NONE,nentries);
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1013
								{
1014
									if( t == DATA_INTEGER )
Kirill Terekhov's avatar
Kirill Terekhov committed
1015
									{
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
										if( newcells[it] != InvalidHandle() )
										{
											Storage::integer_array attrdata = IntegerArray(newcells[it],attr);
											for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
										}
										else for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile;}
									}
									if( t == DATA_REAL )
									{
										if( newcells[it] != InvalidHandle() )
										{
											Storage::real_array attrdata = RealArray(newcells[it],attr);
											for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
										}
										else for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
									}
									if( verbosity > 1 && it%report_pace == 0)
									{
1034 1035 1036 1037
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
Kirill Terekhov's avatar
Kirill Terekhov committed
1038 1039
									}
								}
1040
								datatags.push_back(attr);
Kirill Terekhov's avatar
Kirill Terekhov committed
1041 1042 1043 1044 1045
							}
						}
						if( read_into == 1 )
						{
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newnodes.size()/250),1);
1046
							if( skip )
Kirill Terekhov's avatar
Kirill Terekhov committed
1047
							{
1048
								for(unsigned int it = 0; it < newnodes.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1049
								{
1050 1051 1052 1053 1054 1055
									if( t == DATA_INTEGER )
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile; }
									if( t == DATA_REAL )
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; }
									if( verbosity > 1 && it%report_pace == 0)
									{
1056 1057 1058 1059
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newnodes.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
1060
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
1061
								}
1062 1063 1064 1065 1066
							}
							else
							{
								Tag attr = CreateTag(attrname,t,NODE,NONE,nentries);
								for(unsigned int it = 0; it < newnodes.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1067
								{
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
									if( t == DATA_INTEGER )
									{
										Storage::integer_array attrdata = IntegerArray(newnodes[it],attr);
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
									}
									if( t == DATA_REAL )
									{
										Storage::real_array attrdata = RealArray(newnodes[it],attr);
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile; attrdata[jt] = temp;}
									}
									if( verbosity > 1 && it%report_pace == 0)
									{
1080 1081 1082 1083
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newnodes.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
1084
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
1085 1086
								}
							}
1087
							//filled = fscanf(f,"\n");
Kirill Terekhov's avatar
Kirill Terekhov committed
1088
						}
1089 1090 1091 1092 1093 1094 1095
						
						if( fgets(readline,2048,f) == NULL ) throw BadFile;
						skip_empty(readline,f);
						skip_metadata(3,readline,f);
						skip_empty(readline,f);
						read_next_line = false;
						
Kirill Terekhov's avatar
Kirill Terekhov committed
1096 1097 1098 1099 1100 1101 1102 1103 1104
						break;
					}
					else if( !strcmp(dataname,"TEXTURE_COORDINATES") )
					{
						char attrname[1024];
						char attrtype[1024];
						int nentries;
						DataType t = DATA_BULK;
						filled = sscanf(readline," TEXTURE_COORDINATES %s %d %s",attrname,&nentries,attrtype);
1105
						bool skip = CheckLoadSkip(attrname,noload,loadonly);
1106
						if( verbosity > 0 ) std::cout << (skip?"Skipping":"Reading") << " texture coordinates attribute " << attrname << "\n";
Kirill Terekhov's avatar
Kirill Terekhov committed
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
						if( filled != 3 ) throw BadFile;
						for(unsigned int i = 0; i < strlen(attrtype); i++) attrtype[i] = tolower(attrtype[i]);
						if( !strcmp(attrtype,"bit") || !strcmp(attrtype,"unsigned_char") || !strcmp(attrtype,"char") ||
							  !strcmp(attrtype,"unsigned_short") || !strcmp(attrtype,"short") || !strcmp(attrtype,"unsigned_int") ||
							  !strcmp(attrtype,"int") || !strcmp(attrtype,"unsigned_long") || !strcmp(attrtype,"long"))
							t = DATA_INTEGER;
						else if( !strcmp(attrtype,"float") || !strcmp(attrtype,"double") )
							t = DATA_REAL;
						else
							throw BadFile;
						if( fgets(readline,2048,f) == NULL ) throw BadFile; //LOOK_UP TABLE
						if( read_into == 2 )
						{
1120
							bool sparse = (std::string(attrname).substr(0,9) != "PROTECTED");
Kirill Terekhov's avatar
Kirill Terekhov committed
1121
							unsigned report_pace = std::max<unsigned>(static_cast<unsigned>(newcells.size()/250),1);
1122
							if( skip )
Kirill Terekhov's avatar
Kirill Terekhov committed
1123
							{
1124
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1125
								{
1126 1127 1128 1129 1130
									if( t == DATA_INTEGER )
										for(int jt = 0; jt < nentries; jt++) {int temp; filled = fscanf(f," %d",&temp); if(filled != 1 ) throw BadFile;}
									if( t == DATA_REAL )
										for(int jt = 0; jt < nentries; jt++) {double temp; filled = fscanf(f," %lf",&temp); if(filled != 1 ) throw BadFile;}
									if( verbosity > 1 && it%report_pace == 0)
Kirill Terekhov's avatar
Kirill Terekhov committed
1131
									{
1132 1133 1134 1135
										std::ios save(NULL);
										save.copyfmt(std::cout);
										std::cout << "data " << std::setw(5) << std::fixed << std::setprecision(1) << (it*100.0)/(1.0*newcells.size()) << "%\r" << std::flush;
										std::cout.copyfmt(save);
1136
									}
Kirill Terekhov's avatar
Kirill Terekhov committed
1137
								}
1138 1139 1140 1141 1142
							}
							else
							{
								Tag attr = CreateTag(attrname,t,read_into_cell,sparse ? read_into_cell & ~CELL : NONE,nentries);
								for(unsigned int it = 0; it < newcells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1143
								{
1144
									if( t == DATA_INTEGER )
Kirill Terekhov's avatar
Kirill Terekhov committed
1145
									{
Kirill Terekhov's avatar