Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : /**
17 : : * \class ReadVtk
18 : : * \brief VTK reader from Mesquite
19 : : * \author Jason Kraftcheck
20 : : */
21 : :
22 : : #include <assert.h>
23 : : #include <stdlib.h>
24 : : #include <string.h>
25 : :
26 : : #include "ReadVtk.hpp"
27 : : #include "moab/Range.hpp"
28 : : #include "Internals.hpp"
29 : : #include "moab/Interface.hpp"
30 : : #include "moab/ReadUtilIface.hpp"
31 : : #include "moab/FileOptions.hpp"
32 : : #include "FileTokenizer.hpp"
33 : : #include "moab/VtkUtil.hpp"
34 : : #include "MBTagConventions.hpp"
35 : :
36 : : // #define MB_VTK_MATERIAL_SETS
37 : : #ifdef MB_VTK_MATERIAL_SETS
38 : : #include <map>
39 : : #endif
40 : :
41 : : namespace moab
42 : : {
43 : :
44 : : #ifdef MB_VTK_MATERIAL_SETS
45 : :
46 : : class Hash
47 : : {
48 : : public:
49 : : unsigned long value;
50 : :
51 : : Hash()
52 : : {
53 : : this->value = 5381L;
54 : : }
55 : :
56 : : Hash( const unsigned char* bytes, size_t len )
57 : : { // djb2, a hash by dan bernstein presented on comp.lang.c for hashing strings.
58 : : this->value = 5381L;
59 : : for( ; len; --len, ++bytes )
60 : : this->value = this->value * 33 + ( *bytes );
61 : : }
62 : :
63 : : Hash( bool duh )
64 : : {
65 : : this->value = duh; // Hashing a single bit with a long is stupid but easy.
66 : : }
67 : :
68 : : Hash( const Hash& src )
69 : : {
70 : : this->value = src.value;
71 : : }
72 : :
73 : : Hash& operator=( const Hash& src )
74 : : {
75 : : this->value = src.value;
76 : : return *this;
77 : : }
78 : :
79 : : bool operator<( const Hash& other ) const
80 : : {
81 : : return this->value < other.value;
82 : : }
83 : : };
84 : :
85 : : // Pass this class opaque data + a handle and it adds the handle to a set
86 : : // whose opaque data has the same hash. If no set exists for the hash,
87 : : // it creates one. Each set is tagged with the opaque data.
88 : : // When entities with different opaque data have the same hash, they
89 : : // will be placed into the same set.
90 : : // There will be no collisions when the opaque data is shorter than an
91 : : // unsigned long, and this is really the only case we need to support.
92 : : // The rest is bonus. Hash does quite well with strings, even those
93 : : // with identical prefixes.
94 : : class Modulator : public std::map< Hash, EntityHandle >
95 : : {
96 : : public:
97 : : Modulator( Interface* iface ) : mesh( iface ) {}
98 : :
99 : : ErrorCode initialize( std::string tag_name, DataType mb_type, size_t sz, size_t per_elem )
100 : : {
101 : : std::vector< unsigned char > default_val;
102 : : default_val.resize( sz * per_elem );
103 : : ErrorCode rval = this->mesh->tag_get_handle( tag_name.c_str(), per_elem, mb_type, this->tag,
104 : : MB_TAG_SPARSE | MB_TAG_BYTES | MB_TAG_CREAT, &default_val[0] );
105 : : return rval;
106 : : }
107 : :
108 : : void add_entity( EntityHandle ent, const unsigned char* bytes, size_t len )
109 : : {
110 : : Hash h( bytes, len );
111 : : EntityHandle mset = this->congruence_class( h, bytes );
112 : : ErrorCode rval;
113 : : rval = this->mesh->add_entities( mset, &ent, 1 );MB_CHK_SET_ERR_RET( rval, "Failed to add entities to mesh" );
114 : : }
115 : :
116 : : void add_entities( Range& range, const unsigned char* bytes, size_t bytes_per_ent )
117 : : {
118 : : for( Range::iterator it = range.begin(); it != range.end(); ++it, bytes += bytes_per_ent )
119 : : {
120 : : Hash h( bytes, bytes_per_ent );
121 : : EntityHandle mset = this->congruence_class( h, bytes );
122 : : ErrorCode rval;
123 : : rval = this->mesh->add_entities( mset, &*it, 1 );MB_CHK_SET_ERR_RET( rval, "Failed to add entities to mesh" );
124 : : }
125 : : }
126 : :
127 : : EntityHandle congruence_class( const Hash& h, const void* tag_data )
128 : : {
129 : : std::map< Hash, EntityHandle >::iterator it = this->find( h );
130 : : if( it == this->end() )
131 : : {
132 : : EntityHandle mset;
133 : : Range preexist;
134 : : ErrorCode rval;
135 : : rval = this->mesh->get_entities_by_type_and_tag( 0, MBENTITYSET, &this->tag, &tag_data, 1, preexist );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to get entities by type and tag", (EntityHandle)0 );
136 : : if( preexist.size() ) { mset = *preexist.begin(); }
137 : : else
138 : : {
139 : : rval = this->mesh->create_meshset( MESHSET_SET, mset );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to create mesh set", (EntityHandle)0 );
140 : : rval = this->mesh->tag_set_data( this->tag, &mset, 1, tag_data );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to set tag data", (EntityHandle)0 );
141 : : }
142 : : ( *this )[h] = mset;
143 : : return mset;
144 : : }
145 : : return it->second;
146 : : }
147 : :
148 : : Interface* mesh;
149 : : Tag tag;
150 : : };
151 : : #endif // MB_VTK_MATERIAL_SETS
152 : :
153 : 25 : ReaderIface* ReadVtk::factory( Interface* iface )
154 : : {
155 [ + - ]: 25 : return new ReadVtk( iface );
156 : : }
157 : :
158 [ + - ]: 50 : ReadVtk::ReadVtk( Interface* impl ) : mdbImpl( impl ), mPartitionTagName( MATERIAL_SET_TAG_NAME )
159 : : {
160 [ + - ]: 25 : mdbImpl->query_interface( readMeshIface );
161 : 25 : }
162 : :
163 : 75 : ReadVtk::~ReadVtk()
164 : : {
165 [ + - ]: 25 : if( readMeshIface )
166 : : {
167 : 25 : mdbImpl->release_interface( readMeshIface );
168 : 25 : readMeshIface = 0;
169 : : }
170 [ - + ]: 50 : }
171 : :
172 : : const char* const vtk_type_names[] = {
173 : : "bit", "char", "unsigned_char", "short", "unsigned_short", "int", "unsigned_int",
174 : : "long", "unsigned_long", "float", "double", "vtkIdType", 0
175 : : };
176 : :
177 : 0 : ErrorCode ReadVtk::read_tag_values( const char* /* file_name */, const char* /* tag_name */,
178 : : const FileOptions& /* opts */, std::vector< int >& /* tag_values_out */,
179 : : const SubsetList* /* subset_list */ )
180 : : {
181 : 0 : return MB_NOT_IMPLEMENTED;
182 : : }
183 : :
184 : 25 : ErrorCode ReadVtk::load_file( const char* filename, const EntityHandle* /* file_set */, const FileOptions& opts,
185 : : const ReaderIface::SubsetList* subset_list, const Tag* file_id_tag )
186 : : {
187 : : ErrorCode result;
188 : :
189 : : int major, minor;
190 : : char vendor_string[257];
191 [ + - ]: 25 : std::vector< Range > element_list;
192 [ + - ]: 50 : Range vertices;
193 : :
194 [ - + ][ # # ]: 25 : if( subset_list ) { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for VTK" ); }
[ # # ][ # # ]
[ # # ][ # # ]
195 : :
196 : : // Does the caller want a field to be used for partitioning the entities?
197 : : // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions.
198 [ + - ]: 50 : std::string partition_tag_name;
199 [ + - ]: 25 : result = opts.get_option( "PARTITION", partition_tag_name );
200 [ - + ][ # # ]: 25 : if( result == MB_SUCCESS ) mPartitionTagName = partition_tag_name;
201 : :
202 [ + - ]: 25 : FILE* file = fopen( filename, "r" );
203 [ - + ]: 25 : if( !file ) return MB_FILE_DOES_NOT_EXIST;
204 : :
205 : : // Read file header
206 : :
207 [ + - ][ - + ]: 25 : if( !fgets( vendor_string, sizeof( vendor_string ), file ) )
208 : : {
209 [ # # ]: 0 : fclose( file );
210 : 0 : return MB_FAILURE;
211 : : }
212 : :
213 [ + + ][ - + ]: 25 : if( !strchr( vendor_string, '\n' ) || 2 != sscanf( vendor_string, "# vtk DataFile Version %d.%d", &major, &minor ) )
[ + + ]
214 : : {
215 [ + - ]: 1 : fclose( file );
216 : 1 : return MB_FAILURE;
217 : : }
218 : :
219 [ + - ][ - + ]: 24 : if( !fgets( vendor_string, sizeof( vendor_string ), file ) )
220 : : {
221 [ # # ]: 0 : fclose( file );
222 : 0 : return MB_FAILURE;
223 : : }
224 : :
225 : : // VTK spec says this should not exceed 256 chars.
226 [ - + ]: 24 : if( !strchr( vendor_string, '\n' ) )
227 : : {
228 [ # # ]: 0 : fclose( file );
229 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Vendor string (line 2) exceeds 256 characters" );
[ # # ][ # # ]
[ # # ]
230 : : }
231 : :
232 : : // Check file type
233 : :
234 [ + - ]: 48 : FileTokenizer tokens( file, readMeshIface );
235 : 24 : const char* const file_type_names[] = { "ASCII", "BINARY", 0 };
236 [ + - ]: 24 : int filetype = tokens.match_token( file_type_names );
237 [ - - + ]: 24 : switch( filetype )
238 : : {
239 : : case 2: // BINARY
240 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Cannot read BINARY VTK files" );
[ # # ][ # # ]
[ # # ]
241 : : default: // ERROR
242 : 0 : return MB_FAILURE;
243 : : case 1: // ASCII
244 : 24 : break;
245 : : }
246 : :
247 : : // Read the mesh
248 [ + - ][ - + ]: 24 : if( !tokens.match_token( "DATASET" ) ) return MB_FAILURE;
249 [ + - ]: 24 : result = vtk_read_dataset( tokens, vertices, element_list );
250 [ - + ]: 24 : if( MB_SUCCESS != result ) return result;
251 : :
252 [ - + ]: 24 : if( file_id_tag )
253 : : {
254 [ # # ]: 0 : result = store_file_ids( *file_id_tag, vertices, element_list );
255 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
256 : : }
257 : :
258 : : // Count the number of elements read
259 : 24 : long elem_count = 0;
260 [ + - ][ + - ]: 62 : for( std::vector< Range >::iterator it = element_list.begin(); it != element_list.end(); ++it )
[ + + ]
261 [ + - ][ + - ]: 38 : elem_count += it->size();
262 : :
263 : : // Read attribute data until end of file.
264 : 24 : const char* const block_type_names[] = { "POINT_DATA", "CELL_DATA", 0 };
265 [ + - ]: 24 : std::vector< Range > vertex_list( 1 );
266 [ + - ][ + - ]: 24 : vertex_list[0] = vertices;
267 : 24 : int blocktype = 0;
268 [ + - ][ + + ]: 50 : while( !tokens.eof() )
269 : : {
270 : : // Get POINT_DATA or CELL_DATA
271 [ + - ]: 35 : int new_block_type = tokens.match_token( block_type_names, false );
272 [ + - ][ + + ]: 35 : if( tokens.eof() ) break;
273 : :
274 [ + + ]: 26 : if( !new_block_type )
275 : : {
276 : : // If next token was neither POINT_DATA nor CELL_DATA,
277 : : // then there's another attribute under the current one.
278 [ + - ]: 16 : if( blocktype )
279 [ + - ]: 16 : tokens.unget_token();
280 : : else
281 : 0 : break;
282 : : }
283 : : else
284 : : {
285 : 10 : blocktype = new_block_type;
286 : : long count;
287 [ + - ][ - + ]: 10 : if( !tokens.get_long_ints( 1, &count ) ) return MB_FAILURE;
288 : :
289 [ + + ][ + - ]: 10 : if( blocktype == 1 && (unsigned long)count != vertices.size() )
[ - + ][ - + ]
290 : : {
291 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Count inconsistent with number of vertices at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
292 : : }
293 [ + + ][ - + ]: 10 : else if( blocktype == 2 && count != elem_count )
294 : : {
295 [ # # ][ # # ]: 10 : MB_SET_ERR( MB_FAILURE, "Count inconsistent with number of elements at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
296 : : }
297 : : }
298 : :
299 [ + + ]: 26 : if( blocktype == 1 )
300 [ + - ]: 21 : result = vtk_read_attrib_data( tokens, vertex_list );
301 : : else
302 [ + - ]: 5 : result = vtk_read_attrib_data( tokens, element_list );
303 : :
304 [ - + ]: 26 : if( MB_SUCCESS != result ) return result;
305 : : }
306 : :
307 : 49 : return MB_SUCCESS;
308 : : }
309 : :
310 : 24 : ErrorCode ReadVtk::allocate_vertices( long num_verts, EntityHandle& start_handle_out, double*& x_coord_array_out,
311 : : double*& y_coord_array_out, double*& z_coord_array_out )
312 : : {
313 : : ErrorCode result;
314 : :
315 : : // Create vertices
316 [ + - ]: 24 : std::vector< double* > arrays;
317 : 24 : start_handle_out = 0;
318 [ + - ]: 24 : result = readMeshIface->get_node_coords( 3, num_verts, MB_START_ID, start_handle_out, arrays );
319 [ - + ]: 24 : if( MB_SUCCESS != result ) return result;
320 : :
321 [ + - ]: 24 : x_coord_array_out = arrays[0];
322 [ + - ]: 24 : y_coord_array_out = arrays[1];
323 [ + - ]: 24 : z_coord_array_out = arrays[2];
324 : :
325 : 24 : return MB_SUCCESS;
326 : : }
327 : :
328 : 20 : ErrorCode ReadVtk::read_vertices( FileTokenizer& tokens, long num_verts, EntityHandle& start_handle_out )
329 : : {
330 : : ErrorCode result;
331 : : double *x, *y, *z;
332 : :
333 [ + - ]: 20 : result = allocate_vertices( num_verts, start_handle_out, x, y, z );
334 [ - + ]: 20 : if( MB_SUCCESS != result ) return result;
335 : :
336 : : // Read vertex coordinates
337 [ + + ]: 6051 : for( long vtx = 0; vtx < num_verts; ++vtx )
338 : : {
339 [ + - ][ + - ]: 6031 : if( !tokens.get_doubles( 1, x++ ) || !tokens.get_doubles( 1, y++ ) || !tokens.get_doubles( 1, z++ ) )
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
340 : 0 : return MB_FAILURE;
341 : : }
342 : :
343 : 20 : return MB_SUCCESS;
344 : : }
345 : :
346 : 38 : ErrorCode ReadVtk::allocate_elements( long num_elements, int vert_per_element, EntityType type,
347 : : EntityHandle& start_handle_out, EntityHandle*& conn_array_out,
348 : : std::vector< Range >& append_to_this )
349 : : {
350 : : ErrorCode result;
351 : :
352 : 38 : start_handle_out = 0;
353 : : result = readMeshIface->get_element_connect( num_elements, vert_per_element, type, MB_START_ID, start_handle_out,
354 [ + - ]: 38 : conn_array_out );
355 [ - + ]: 38 : if( MB_SUCCESS != result ) return result;
356 : :
357 [ + - ]: 38 : Range range( start_handle_out, start_handle_out + num_elements - 1 );
358 [ + - ]: 38 : append_to_this.push_back( range );
359 : 38 : return MB_SUCCESS;
360 : : }
361 : :
362 : 24 : ErrorCode ReadVtk::vtk_read_dataset( FileTokenizer& tokens, Range& vertex_list, std::vector< Range >& element_list )
363 : : {
364 : : const char* const data_type_names[] = {
365 : : "STRUCTURED_POINTS", "STRUCTURED_GRID", "UNSTRUCTURED_GRID", "POLYDATA", "RECTILINEAR_GRID", "FIELD", 0
366 : 24 : };
367 [ + - ]: 24 : int datatype = tokens.match_token( data_type_names );
368 [ + - + - : 24 : switch( datatype )
- - - ]
369 : : {
370 : : case 1:
371 [ + - ]: 4 : return vtk_read_structured_points( tokens, vertex_list, element_list );
372 : : case 2:
373 [ # # ]: 0 : return vtk_read_structured_grid( tokens, vertex_list, element_list );
374 : : case 3:
375 [ + - ]: 20 : return vtk_read_unstructured_grid( tokens, vertex_list, element_list );
376 : : case 4:
377 [ # # ]: 0 : return vtk_read_polydata( tokens, vertex_list, element_list );
378 : : case 5:
379 [ # # ]: 0 : return vtk_read_rectilinear_grid( tokens, vertex_list, element_list );
380 : : case 6:
381 [ # # ]: 0 : return vtk_read_field( tokens );
382 : : default:
383 : 24 : return MB_FAILURE;
384 : : }
385 : : }
386 : :
387 : 4 : ErrorCode ReadVtk::vtk_read_structured_points( FileTokenizer& tokens, Range& vertex_list,
388 : : std::vector< Range >& elem_list )
389 : : {
390 : : long i, j, k;
391 : : long dims[3];
392 : : double origin[3], space[3];
393 : : ErrorCode result;
394 : :
395 [ + - ][ + - ]: 4 : if( !tokens.match_token( "DIMENSIONS" ) || !tokens.get_long_ints( 3, dims ) || !tokens.get_newline() )
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
396 : 0 : return MB_FAILURE;
397 : :
398 [ + - ][ + - ]: 4 : if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
[ - + ]
399 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Invalid dimension at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
400 : :
401 [ + - ][ + - ]: 4 : if( !tokens.match_token( "ORIGIN" ) || !tokens.get_doubles( 3, origin ) || !tokens.get_newline() )
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
402 : 0 : return MB_FAILURE;
403 : :
404 : 4 : const char* const spacing_names[] = { "SPACING", "ASPECT_RATIO", 0 };
405 [ + - ][ + - ]: 4 : if( !tokens.match_token( spacing_names ) || !tokens.get_doubles( 3, space ) || !tokens.get_newline() )
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
406 : 0 : return MB_FAILURE;
407 : :
408 : : // Create vertices
409 : : double *x, *y, *z;
410 : 4 : EntityHandle start_handle = 0;
411 : 4 : long num_verts = dims[0] * dims[1] * dims[2];
412 [ + - ]: 4 : result = allocate_vertices( num_verts, start_handle, x, y, z );
413 [ - + ]: 4 : if( MB_SUCCESS != result ) return result;
414 [ + - ]: 4 : vertex_list.insert( start_handle, start_handle + num_verts - 1 );
415 : :
416 [ + + ]: 26 : for( k = 0; k < dims[2]; ++k )
417 [ + + ]: 242 : for( j = 0; j < dims[1]; ++j )
418 [ + + ]: 2420 : for( i = 0; i < dims[0]; ++i )
419 : : {
420 : 2200 : *x = origin[0] + i * space[0];
421 : 2200 : ++x;
422 : 2200 : *y = origin[1] + j * space[1];
423 : 2200 : ++y;
424 : 2200 : *z = origin[2] + k * space[2];
425 : 2200 : ++z;
426 : : }
427 : :
428 [ + - ]: 4 : return vtk_create_structured_elems( dims, start_handle, elem_list );
429 : : }
430 : :
431 : 0 : ErrorCode ReadVtk::vtk_read_structured_grid( FileTokenizer& tokens, Range& vertex_list,
432 : : std::vector< Range >& elem_list )
433 : : {
434 : : long num_verts, dims[3];
435 : : ErrorCode result;
436 : :
437 [ # # ][ # # ]: 0 : if( !tokens.match_token( "DIMENSIONS" ) || !tokens.get_long_ints( 3, dims ) || !tokens.get_newline() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
438 : 0 : return MB_FAILURE;
439 : :
440 [ # # ][ # # ]: 0 : if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
[ # # ]
441 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Invalid dimension at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
442 : :
443 [ # # ][ # # ]: 0 : if( !tokens.match_token( "POINTS" ) || !tokens.get_long_ints( 1, &num_verts ) ||
[ # # ][ # # ]
[ # # ]
444 [ # # ][ # # ]: 0 : !tokens.match_token( vtk_type_names ) || !tokens.get_newline() )
[ # # ][ # # ]
445 : 0 : return MB_FAILURE;
446 : :
447 [ # # ]: 0 : if( num_verts != ( dims[0] * dims[1] * dims[2] ) )
448 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Point count not consistent with dimensions at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
449 : :
450 : : // Create and read vertices
451 : 0 : EntityHandle start_handle = 0;
452 [ # # ]: 0 : result = read_vertices( tokens, num_verts, start_handle );
453 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
454 [ # # ]: 0 : vertex_list.insert( start_handle, start_handle + num_verts - 1 );
455 : :
456 [ # # ]: 0 : return vtk_create_structured_elems( dims, start_handle, elem_list );
457 : : }
458 : :
459 : 0 : ErrorCode ReadVtk::vtk_read_rectilinear_grid( FileTokenizer& tokens, Range& vertex_list,
460 : : std::vector< Range >& elem_list )
461 : : {
462 : : int i, j, k;
463 : : long dims[3];
464 : 0 : const char* labels[] = { "X_COORDINATES", "Y_COORDINATES", "Z_COORDINATES" };
465 [ # # ][ # # ]: 0 : std::vector< double > coords[3];
[ # # ]
466 : : ErrorCode result;
467 : :
468 [ # # ][ # # ]: 0 : if( !tokens.match_token( "DIMENSIONS" ) || !tokens.get_long_ints( 3, dims ) || !tokens.get_newline() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
469 : 0 : return MB_FAILURE;
470 : :
471 [ # # ][ # # ]: 0 : if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
[ # # ]
472 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Invalid dimension at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
473 : :
474 [ # # ]: 0 : for( i = 0; i < 3; i++ )
475 : : {
476 : : long count;
477 [ # # ][ # # ]: 0 : if( !tokens.match_token( labels[i] ) || !tokens.get_long_ints( 1, &count ) ||
[ # # ][ # # ]
[ # # ][ # # ]
478 [ # # ]: 0 : !tokens.match_token( vtk_type_names ) )
479 : 0 : return MB_FAILURE;
480 : :
481 [ # # ]: 0 : if( count != dims[i] )
482 : : {
483 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Coordinate count inconsistent with dimensions at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
484 : : }
485 : :
486 [ # # ]: 0 : coords[i].resize( count );
487 [ # # ][ # # ]: 0 : if( !tokens.get_doubles( count, &coords[i][0] ) ) return MB_FAILURE;
[ # # ]
488 : : }
489 : :
490 : : // Create vertices
491 : : double *x, *y, *z;
492 : 0 : EntityHandle start_handle = 0;
493 : 0 : long num_verts = dims[0] * dims[1] * dims[2];
494 [ # # ]: 0 : result = allocate_vertices( num_verts, start_handle, x, y, z );
495 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
496 [ # # ]: 0 : vertex_list.insert( start_handle, start_handle + num_verts - 1 );
497 : :
498 : : // Calculate vertex coordinates
499 [ # # ]: 0 : for( k = 0; k < dims[2]; ++k )
500 [ # # ]: 0 : for( j = 0; j < dims[1]; ++j )
501 [ # # ]: 0 : for( i = 0; i < dims[0]; ++i )
502 : : {
503 [ # # ]: 0 : *x = coords[0][i];
504 : 0 : ++x;
505 [ # # ]: 0 : *y = coords[1][j];
506 : 0 : ++y;
507 [ # # ]: 0 : *z = coords[2][k];
508 : 0 : ++z;
509 : : }
510 : :
511 [ # # ][ # # ]: 0 : return vtk_create_structured_elems( dims, start_handle, elem_list );
[ # # # # ]
512 : : }
513 : :
514 : 0 : ErrorCode ReadVtk::vtk_read_polydata( FileTokenizer& tokens, Range& vertex_list, std::vector< Range >& elem_list )
515 : : {
516 : : ErrorCode result;
517 : : long num_verts;
518 : 0 : const char* const poly_data_names[] = { "VERTICES", "LINES", "POLYGONS", "TRIANGLE_STRIPS", 0 };
519 : :
520 [ # # ][ # # ]: 0 : if( !tokens.match_token( "POINTS" ) || !tokens.get_long_ints( 1, &num_verts ) ||
[ # # ][ # # ]
[ # # ]
521 [ # # ][ # # ]: 0 : !tokens.match_token( vtk_type_names ) || !tokens.get_newline() )
[ # # ][ # # ]
522 : 0 : return MB_FAILURE;
523 : :
524 [ # # ][ # # ]: 0 : if( num_verts < 1 ) { MB_SET_ERR( MB_FAILURE, "Invalid point count at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
525 : :
526 : : // Create vertices and read coordinates
527 : 0 : EntityHandle start_handle = 0;
528 [ # # ]: 0 : result = read_vertices( tokens, num_verts, start_handle );
529 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
530 [ # # ]: 0 : vertex_list.insert( start_handle, start_handle + num_verts - 1 );
531 : :
532 [ # # ]: 0 : int poly_type = tokens.match_token( poly_data_names );
533 [ # # # # : 0 : switch( poly_type )
# # ]
534 : : {
535 : : case 0:
536 : 0 : result = MB_FAILURE;
537 : 0 : break;
538 : : case 1:
539 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Vertex element type at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
540 : : break;
541 : : case 2:
542 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unsupported type: polylines at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
543 : : result = MB_FAILURE;
544 : : break;
545 : : case 3:
546 [ # # ]: 0 : result = vtk_read_polygons( tokens, start_handle, elem_list );
547 : 0 : break;
548 : : case 4:
549 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unsupported type: triangle strips at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
550 : : result = MB_FAILURE;
551 : : break;
552 : : }
553 : :
554 : 0 : return result;
555 : : }
556 : :
557 : 0 : ErrorCode ReadVtk::vtk_read_polygons( FileTokenizer& tokens, EntityHandle first_vtx, std::vector< Range >& elem_list )
558 : : {
559 : : ErrorCode result;
560 : : long size[2];
561 : :
562 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 2, size ) || !tokens.get_newline() ) return MB_FAILURE;
[ # # ][ # # ]
[ # # ]
563 : :
564 [ # # ]: 0 : const Range empty;
565 [ # # ]: 0 : std::vector< EntityHandle > conn_hdl;
566 [ # # ]: 0 : std::vector< long > conn_idx;
567 : 0 : EntityHandle first = 0, prev = 0, handle;
568 [ # # ]: 0 : for( int i = 0; i < size[0]; ++i )
569 : : {
570 : : long count;
571 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 1, &count ) ) return MB_FAILURE;
572 [ # # ]: 0 : conn_idx.resize( count );
573 [ # # ]: 0 : conn_hdl.resize( count );
574 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( count, &conn_idx[0] ) ) return MB_FAILURE;
[ # # ]
575 : :
576 [ # # ]: 0 : for( long j = 0; j < count; ++j )
577 [ # # ][ # # ]: 0 : conn_hdl[j] = first_vtx + conn_idx[j];
578 : :
579 [ # # ][ # # ]: 0 : result = mdbImpl->create_element( MBPOLYGON, &conn_hdl[0], count, handle );
580 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
581 : :
582 [ # # ]: 0 : if( prev + 1 != handle )
583 : : {
584 [ # # ]: 0 : if( first )
585 : : { // True except for first iteration (first == 0)
586 [ # # ][ # # ]: 0 : if( elem_list.empty() || first < elem_list.back().front() ) // Only need new range if order would get
[ # # ][ # # ]
[ # # ]
587 : : // mixed up, or we just began inserting
588 [ # # ]: 0 : elem_list.push_back( empty );
589 [ # # ][ # # ]: 0 : elem_list.back().insert( first, prev );
590 : : }
591 : 0 : first = handle;
592 : : }
593 : 0 : prev = handle;
594 : : }
595 [ # # ]: 0 : if( first )
596 : : { // True unless no elements (size[0] == 0)
597 [ # # ][ # # ]: 0 : if( elem_list.empty() || first < elem_list.back().front() ) // Only need new range if order would get mixed
[ # # ][ # # ]
[ # # ]
598 : : // up, or we just began inserting
599 [ # # ]: 0 : elem_list.push_back( empty );
600 [ # # ][ # # ]: 0 : elem_list.back().insert( first, prev );
601 : : }
602 : :
603 : 0 : return MB_SUCCESS;
604 : : }
605 : :
606 : 20 : ErrorCode ReadVtk::vtk_read_unstructured_grid( FileTokenizer& tokens, Range& vertex_list,
607 : : std::vector< Range >& elem_list )
608 : : {
609 : : ErrorCode result;
610 : : long i, num_verts, num_elems[2];
611 : : EntityHandle tmp_conn_list[27];
612 : :
613 : : // Poorly formatted VTK legacy format document seems to
614 : : // lead many to think that a FIELD block can occur within
615 : : // an UNSTRUCTURED_GRID dataset rather than as its own data
616 : : // set. So allow for field data between other blocks of
617 : : // data.
618 : :
619 : 20 : const char* pts_str[] = { "FIELD", "POINTS", 0 };
620 [ + - ][ - + ]: 20 : while( 1 == ( i = tokens.match_token( pts_str ) ) )
621 : : {
622 [ # # ]: 0 : result = vtk_read_field( tokens );
623 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
624 : : }
625 [ - + ]: 20 : if( i != 2 ) return MB_FAILURE;
626 : :
627 [ + - ][ + - ]: 20 : if( !tokens.get_long_ints( 1, &num_verts ) || !tokens.match_token( vtk_type_names ) || !tokens.get_newline() )
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
628 : 0 : return MB_FAILURE;
629 : :
630 [ - + ][ # # ]: 20 : if( num_verts < 1 ) { MB_SET_ERR( MB_FAILURE, "Invalid point count at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
631 : :
632 : : // Create vertices and read coordinates
633 : 20 : EntityHandle first_vertex = 0;
634 [ + - ]: 20 : result = read_vertices( tokens, num_verts, first_vertex );
635 [ - + ]: 20 : if( MB_SUCCESS != result ) return result;
636 [ + - ]: 20 : vertex_list.insert( first_vertex, first_vertex + num_verts - 1 );
637 : :
638 : 20 : const char* cell_str[] = { "FIELD", "CELLS", 0 };
639 [ + - ][ - + ]: 20 : while( 1 == ( i = tokens.match_token( cell_str ) ) )
640 : : {
641 [ # # ]: 0 : result = vtk_read_field( tokens );
642 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
643 : : }
644 [ - + ]: 20 : if( i != 2 ) return MB_FAILURE;
645 : :
646 [ + - ][ + - ]: 20 : if( !tokens.get_long_ints( 2, num_elems ) || !tokens.get_newline() ) return MB_FAILURE;
[ + - ][ - + ]
[ - + ]
647 : :
648 : : // Read element connectivity for all elements
649 [ + - ]: 20 : std::vector< long > connectivity( num_elems[1] );
650 [ + - ][ + - ]: 20 : if( !tokens.get_long_ints( num_elems[1], &connectivity[0] ) ) return MB_FAILURE;
[ - + ]
651 : :
652 [ + - ][ + - ]: 20 : if( !tokens.match_token( "CELL_TYPES" ) || !tokens.get_long_ints( 1, &num_elems[1] ) || !tokens.get_newline() )
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
653 : 0 : return MB_FAILURE;
654 : :
655 : : // Read element types
656 [ + - ]: 40 : std::vector< long > types( num_elems[0] );
657 [ + - ][ + - ]: 20 : if( !tokens.get_long_ints( num_elems[0], &types[0] ) ) return MB_FAILURE;
[ - + ]
658 : :
659 : : // Create elements in blocks of the same type
660 : : // It is important to preserve the order in
661 : : // which the elements were read for later reading
662 : : // attribute data.
663 : 20 : long id = 0;
664 : 20 : std::vector< long >::iterator conn_iter = connectivity.begin();
665 [ + + ]: 54 : while( id < num_elems[0] )
666 : : {
667 [ + - ]: 34 : unsigned vtk_type = types[id];
668 [ - + ]: 34 : if( vtk_type >= VtkUtil::numVtkElemType ) return MB_FAILURE;
669 : :
670 : 34 : EntityType type = VtkUtil::vtkElemTypes[vtk_type].mb_type;
671 [ - + ]: 34 : if( type == MBMAXTYPE )
672 : : {
673 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unsupported VTK element type: " << VtkUtil::vtkElemTypes[vtk_type].name << " ("
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
674 : : << vtk_type << ")" );
675 : : }
676 : :
677 [ + - ]: 34 : int num_vtx = *conn_iter;
678 [ + - ][ + - ]: 34 : if( type != MBPOLYGON && type != MBPOLYHEDRON && num_vtx != (int)VtkUtil::vtkElemTypes[vtk_type].num_nodes )
[ - + ]
679 : : {
680 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Cell " << id << " is of type '" << VtkUtil::vtkElemTypes[vtk_type].name
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
681 : : << "' but has " << num_vtx << " vertices" );
682 : : }
683 : :
684 : : // Find any subsequent elements of the same type
685 : : // if polyhedra, need to look at the number of faces to put in the same range
686 [ + - ][ + - ]: 34 : std::vector< long >::iterator conn_iter2 = conn_iter + num_vtx + 1;
687 : 34 : long end_id = id + 1;
688 [ + - ]: 34 : if( MBPOLYHEDRON != type )
689 : : {
690 [ + + ][ + - ]: 12177 : while( end_id < num_elems[0] && (unsigned)types[end_id] == vtk_type && *conn_iter2 == num_vtx )
[ + + ][ + - ]
[ + - ][ + + ]
691 : : {
692 : 12143 : ++end_id;
693 [ + - ]: 12143 : conn_iter2 += num_vtx + 1;
694 : : }
695 : : }
696 : : else
697 : : {
698 : : // advance only if next is polyhedron too, and if number of faces is the same
699 [ # # ]: 0 : int num_faces = conn_iter[1];
700 [ # # ][ # # ]: 0 : while( end_id < num_elems[0] && (unsigned)types[end_id] == vtk_type && conn_iter2[1] == num_faces )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
701 : : {
702 : 0 : ++end_id;
703 [ # # ]: 0 : conn_iter2 += num_vtx + 1;
704 : : }
705 : : // num_vtx becomes in this case num_faces
706 : 0 : num_vtx = num_faces; // for polyhedra, this is what we want
707 : : // trigger vertex adjacency call
708 [ # # ]: 0 : Range firstFaces;
709 [ # # ]: 0 : mdbImpl->get_adjacencies( &first_vertex, 1, 2, false, firstFaces );
710 : : }
711 : :
712 : : // Allocate element block
713 : 34 : long num_elem = end_id - id;
714 : 34 : EntityHandle start_handle = 0;
715 : : EntityHandle* conn_array;
716 : :
717 : : // if type is MBVERTEX, skip, we will not create elements with one vertex
718 [ - + ]: 34 : if( MBVERTEX == type )
719 : : {
720 : 0 : id += num_elem;
721 [ # # ]: 0 : conn_iter += 2 * num_elem; // skip 2 * number of 1-vertex elements
722 : 0 : continue;
723 : : }
724 : :
725 [ + - ]: 34 : result = allocate_elements( num_elem, num_vtx, type, start_handle, conn_array, elem_list );
726 [ - + ]: 34 : if( MB_SUCCESS != result ) return result;
727 : :
728 : 34 : EntityHandle* conn_sav = conn_array;
729 : :
730 : : // Store element connectivity
731 [ + - ]: 34 : if( type != MBPOLYHEDRON )
732 : : {
733 [ + + ]: 12211 : for( ; id < end_id; ++id )
734 : : {
735 [ + - ][ - + ]: 12177 : if( conn_iter == connectivity.end() )
736 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Connectivity data truncated at cell " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
737 : : // Make sure connectivity length is correct.
738 [ + - ][ - + ]: 12177 : if( *conn_iter != num_vtx )
739 : : {
740 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Cell " << id << " is of type '" << VtkUtil::vtkElemTypes[vtk_type].name
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
741 : : << "' but has " << num_vtx << " vertices" );
742 : : }
743 [ + - ]: 12177 : ++conn_iter;
744 : :
745 [ + - ][ + + ]: 57097 : for( i = 0; i < num_vtx; ++i, ++conn_iter )
746 : : {
747 [ + - ][ - + ]: 44920 : if( conn_iter == connectivity.end() )
748 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Connectivity data truncated at cell " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
749 : :
750 [ + - ]: 44920 : conn_array[i] = *conn_iter + first_vertex;
751 : : }
752 : :
753 : 12177 : const unsigned* order = VtkUtil::vtkElemTypes[vtk_type].node_order;
754 [ - + ]: 12177 : if( order )
755 : : {
756 [ # # ]: 0 : assert( num_vtx * sizeof( EntityHandle ) <= sizeof( tmp_conn_list ) );
757 : 0 : memcpy( tmp_conn_list, conn_array, num_vtx * sizeof( EntityHandle ) );
758 [ # # ]: 0 : for( int j = 0; j < num_vtx; ++j )
759 : 0 : conn_array[order[j]] = tmp_conn_list[j];
760 : : }
761 : :
762 : 12177 : conn_array += num_vtx;
763 : : }
764 : : }
765 : : else // type == MBPOLYHEDRON
766 : : {
767 : : // in some cases, we may need to create new elements; will it screw the tags?
768 : : // not if the file was not from moab
769 : 0 : ErrorCode rv = MB_SUCCESS;
770 [ # # ]: 0 : for( ; id < end_id; ++id )
771 : : {
772 [ # # ][ # # ]: 0 : if( conn_iter == connectivity.end() )
773 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Connectivity data truncated at polyhedra cell " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
774 [ # # ]: 0 : ++conn_iter;
775 : : // iterator is now at number of faces
776 : : // we should check it is indeed num_vtx
777 [ # # ]: 0 : int num_faces = *conn_iter;
778 [ # # ][ # # ]: 0 : if( num_faces != num_vtx ) MB_SET_ERR( MB_FAILURE, "Connectivity data wrong at polyhedra cell " << id );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
779 : :
780 : : EntityHandle connec[20]; // we bet we will have only 20 vertices at most, in a
781 : : // face in a polyhedra
782 [ # # ]: 0 : for( int j = 0; j < num_faces; j++ )
783 : : {
784 [ # # ]: 0 : conn_iter++;
785 [ # # ]: 0 : int numverticesInFace = (int)*conn_iter;
786 [ # # ]: 0 : if( numverticesInFace > 20 )
787 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
788 : : "too many vertices in face index " << j << " for polyhedra cell " << id );
789 : : // need to find the face, but first fill with vertices
790 [ # # ]: 0 : for( int k = 0; k < numverticesInFace; k++ )
791 : : {
792 [ # # ][ # # ]: 0 : connec[k] = first_vertex + *( ++conn_iter ); //
793 : : }
794 [ # # ]: 0 : Range adjFaces;
795 : : // find a face with these vertices; if not, we need to create one, on the fly :(
796 [ # # ][ # # ]: 0 : rv = mdbImpl->get_adjacencies( connec, numverticesInFace, 2, false, adjFaces );MB_CHK_ERR( rv );
[ # # ][ # # ]
797 [ # # ][ # # ]: 0 : if( adjFaces.size() >= 1 )
798 : : {
799 [ # # ]: 0 : conn_array[j] = adjFaces[0]; // get the first face found
800 : : }
801 : : else
802 : : {
803 : : // create the face; tri, quad or polygon
804 : 0 : EntityType etype = MBTRI;
805 [ # # ]: 0 : if( 4 == numverticesInFace ) etype = MBQUAD;
806 [ # # ]: 0 : if( 4 < numverticesInFace ) etype = MBPOLYGON;
807 : :
808 [ # # ][ # # ]: 0 : rv = mdbImpl->create_element( etype, connec, numverticesInFace, conn_array[j] );MB_CHK_ERR( rv );
[ # # ][ # # ]
[ # # ]
809 : : }
810 : 0 : }
811 : :
812 : 0 : conn_array += num_vtx; // advance for next polyhedra
813 [ # # ]: 0 : conn_iter++; // advance to the next field
814 : : }
815 : : }
816 : :
817 : : // Notify MOAB of the new elements
818 [ + - ]: 34 : result = readMeshIface->update_adjacencies( start_handle, num_elem, num_vtx, conn_sav );
819 [ - + ]: 34 : if( MB_SUCCESS != result ) return result;
820 : : }
821 : :
822 : 40 : return MB_SUCCESS;
823 : : }
824 : :
825 : 4 : ErrorCode ReadVtk::vtk_create_structured_elems( const long* dims, EntityHandle first_vtx,
826 : : std::vector< Range >& elem_list )
827 : : {
828 : : ErrorCode result;
829 : : // int non_zero[3] = {0, 0, 0}; // True if dim > 0 for x, y, z respectively
830 : 4 : long elem_dim = 0; // Element dimension (2->quad, 3->hex)
831 : 4 : long num_elems = 1; // Total number of elements
832 : : long vert_per_elem; // Element connectivity length
833 : 4 : long edims[3] = { 1, 1, 1 }; // Number of elements in each grid direction
834 : :
835 : : // Populate above data
836 [ + + ]: 16 : for( int d = 0; d < 3; d++ )
837 : : {
838 [ + + ]: 12 : if( dims[d] > 1 )
839 : : {
840 : : // non_zero[elem_dim] = d;
841 : 10 : ++elem_dim;
842 : 10 : edims[d] = dims[d] - 1;
843 : 10 : num_elems *= edims[d];
844 : : }
845 : : }
846 : 4 : vert_per_elem = 1 << elem_dim;
847 : :
848 : : // Get element type from element dimension
849 : : EntityType type;
850 [ - + + - ]: 4 : switch( elem_dim )
851 : : {
852 : : case 1:
853 : 0 : type = MBEDGE;
854 : 0 : break;
855 : : case 2:
856 : 2 : type = MBQUAD;
857 : 2 : break;
858 : : case 3:
859 : 2 : type = MBHEX;
860 : 2 : break;
861 : : default:
862 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Invalid dimension for structured elements: " << elem_dim );
[ # # ][ # # ]
[ # # ][ # # ]
863 : : }
864 : :
865 : : // Allocate storage for elements
866 : 4 : EntityHandle start_handle = 0;
867 : : EntityHandle* conn_array;
868 [ + - ]: 4 : result = allocate_elements( num_elems, vert_per_elem, type, start_handle, conn_array, elem_list );
869 [ - + ]: 4 : if( MB_SUCCESS != result ) return MB_FAILURE;
870 : :
871 : 4 : EntityHandle* conn_sav = conn_array;
872 : :
873 : : // Offsets of element vertices in grid relative to corner closest to origin
874 : 4 : long k = dims[0] * dims[1];
875 : 4 : const long corners[8] = { 0, 1, 1 + dims[0], dims[0], k, k + 1, k + 1 + dims[0], k + dims[0] };
876 : :
877 : : // Populate element list
878 [ + + ]: 24 : for( long z = 0; z < edims[2]; ++z )
879 [ + + ]: 200 : for( long y = 0; y < edims[1]; ++y )
880 [ + + ]: 1800 : for( long x = 0; x < edims[0]; ++x )
881 : : {
882 : 1620 : const long index = x + y * dims[0] + z * ( dims[0] * dims[1] );
883 [ + + ]: 13932 : for( long j = 0; j < vert_per_elem; ++j, ++conn_array )
884 : 12312 : *conn_array = index + corners[j] + first_vtx;
885 : : }
886 : :
887 : : // Notify MOAB of the new elements
888 [ + - ]: 4 : result = readMeshIface->update_adjacencies( start_handle, num_elems, vert_per_elem, conn_sav );
889 [ - + ]: 4 : if( MB_SUCCESS != result ) return result;
890 : :
891 : 4 : return MB_SUCCESS;
892 : : }
893 : :
894 : 0 : ErrorCode ReadVtk::vtk_read_field( FileTokenizer& tokens )
895 : : {
896 : : // This is not supported yet.
897 : : // Parse the data but throw it away because
898 : : // Mesquite has no internal representation for it.
899 : :
900 : : // Could save this in tags, but the only useful thing that
901 : : // could be done with the data is to write it back out
902 : : // with the modified mesh. As there's no way to save the
903 : : // type of a tag in Mesquite, it cannot be written back
904 : : // out correctly either.
905 : : // FIXME: Don't know what to do with this data.
906 : : // For now, read it and throw it out.
907 : :
908 : : long num_arrays;
909 [ # # ][ # # ]: 0 : if( !tokens.get_string() || // Name
[ # # ][ # # ]
910 [ # # ]: 0 : !tokens.get_long_ints( 1, &num_arrays ) )
911 : 0 : return MB_FAILURE;
912 : :
913 [ # # ]: 0 : for( long i = 0; i < num_arrays; ++i )
914 : : {
915 [ # # ]: 0 : /*const char* name =*/tokens.get_string();
916 : :
917 : : long dims[2];
918 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 2, dims ) || !tokens.match_token( vtk_type_names ) ) return MB_FAILURE;
[ # # ][ # # ]
[ # # ]
919 : :
920 : 0 : long num_vals = dims[0] * dims[1];
921 : :
922 [ # # ]: 0 : for( long j = 0; j < num_vals; j++ )
923 : : {
924 : : double junk;
925 [ # # ][ # # ]: 0 : if( !tokens.get_doubles( 1, &junk ) ) return MB_FAILURE;
926 : : }
927 : : }
928 : :
929 : 0 : return MB_SUCCESS;
930 : : }
931 : :
932 : 26 : ErrorCode ReadVtk::vtk_read_attrib_data( FileTokenizer& tokens, std::vector< Range >& entities )
933 : : {
934 : : const char* const type_names[] = { "SCALARS", "COLOR_SCALARS", "VECTORS", "NORMALS", "TEXTURE_COORDINATES",
935 : 26 : "TENSORS", "FIELD", 0 };
936 : :
937 [ + - ]: 26 : int type = tokens.match_token( type_names );
938 [ + - ]: 26 : const char* tmp_name = tokens.get_string();
939 [ + - ][ - + ]: 26 : if( !type || !tmp_name ) return MB_FAILURE;
940 : :
941 [ + - ]: 26 : std::string name_alloc( tmp_name );
942 : 26 : const char* name = name_alloc.c_str();
943 [ + - + - : 26 : switch( type )
- - - - ]
944 : : {
945 : : case 1:
946 [ + - ]: 22 : return vtk_read_scalar_attrib( tokens, entities, name );
947 : : case 2:
948 [ # # ]: 0 : return vtk_read_color_attrib( tokens, entities, name );
949 : : case 3:
950 [ + - ]: 4 : return vtk_read_vector_attrib( tokens, entities, name );
951 : : case 4:
952 [ # # ]: 0 : return vtk_read_vector_attrib( tokens, entities, name );
953 : : case 5:
954 [ # # ]: 0 : return vtk_read_texture_attrib( tokens, entities, name );
955 : : case 6:
956 [ # # ]: 0 : return vtk_read_tensor_attrib( tokens, entities, name );
957 : : case 7:
958 [ # # ]: 0 : return vtk_read_field_attrib( tokens, entities, name );
959 : : }
960 : :
961 : 26 : return MB_FAILURE;
962 : : }
963 : :
964 : 26 : ErrorCode ReadVtk::vtk_read_tag_data( FileTokenizer& tokens, int type, size_t per_elem, std::vector< Range >& entities,
965 : : const char* name )
966 : : {
967 : : ErrorCode result;
968 : : DataType mb_type;
969 [ - + ]: 26 : if( type == 1 ) { mb_type = MB_TYPE_BIT; }
970 [ + - ][ + + ]: 26 : else if( type >= 2 && type <= 9 )
971 : : {
972 : 14 : mb_type = MB_TYPE_INTEGER;
973 : : }
974 [ + - ][ + - ]: 12 : else if( type == 10 || type == 11 )
975 : : {
976 : 12 : mb_type = MB_TYPE_DOUBLE;
977 : : }
978 [ # # ]: 0 : else if( type == 12 )
979 : : {
980 : 0 : mb_type = MB_TYPE_INTEGER;
981 : : }
982 : : else
983 : 0 : return MB_FAILURE;
984 : :
985 : : #ifdef MB_VTK_MATERIAL_SETS
986 : : size_t size;
987 : : if( type == 1 ) { size = sizeof( bool ); }
988 : : else if( type >= 2 && type <= 9 )
989 : : {
990 : : size = sizeof( int );
991 : : }
992 : : else if( type == 10 || type == 11 )
993 : : {
994 : : size = sizeof( double );
995 : : }
996 : : else /* (type == 12) */
997 : : {
998 : : size = 4; // Could be 4 or 8, but we don't know. Hope it's 4 because MOAB doesn't support
999 : : // 64-bit ints.
1000 : : }
1001 : : Modulator materialMap( this->mdbImpl );
1002 : : result = materialMap.initialize( this->mPartitionTagName, mb_type, size, per_elem );MB_CHK_SET_ERR( result, "MaterialMap tag (" << this->mPartitionTagName << ") creation failed." );
1003 : : bool isMaterial = size * per_elem <= 4 && // Must have int-sized values (ParallelComm requires it)
1004 : : !this->mPartitionTagName.empty() && // Must have a non-empty field name...
1005 : : !strcmp( name, this->mPartitionTagName.c_str() ); // ... that matches our spec.
1006 : : #endif // MB_VTK_MATERIAL_SETS
1007 : :
1008 : : // Get/create tag
1009 : : Tag handle;
1010 [ + - ][ - + ]: 26 : result = mdbImpl->tag_get_handle( name, per_elem, mb_type, handle, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( result, "Tag name conflict for attribute \"" << name << "\" at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1011 : :
1012 : 26 : std::vector< Range >::iterator iter;
1013 : :
1014 [ - + ]: 26 : if( type == 1 )
1015 : : {
1016 [ # # ][ # # ]: 0 : for( iter = entities.begin(); iter != entities.end(); ++iter )
[ # # ]
1017 : : {
1018 [ # # ][ # # ]: 0 : bool* data = new bool[iter->size() * per_elem];
[ # # ]
1019 [ # # ][ # # ]: 0 : if( !tokens.get_booleans( per_elem * iter->size(), data ) )
[ # # ][ # # ]
1020 : : {
1021 [ # # ]: 0 : delete[] data;
1022 : 0 : return MB_FAILURE;
1023 : : }
1024 : :
1025 : 0 : bool* data_iter = data;
1026 [ # # ][ # # ]: 0 : Range::iterator ent_iter = iter->begin();
1027 [ # # ][ # # ]: 0 : for( ; ent_iter != iter->end(); ++ent_iter )
[ # # ][ # # ]
[ # # ]
1028 : : {
1029 : 0 : unsigned char bits = 0;
1030 [ # # ]: 0 : for( unsigned j = 0; j < per_elem; ++j, ++data_iter )
1031 : 0 : bits |= (unsigned char)( *data_iter << j );
1032 : : #ifdef MB_VTK_MATERIAL_SETS
1033 : : if( isMaterial ) materialMap.add_entity( *ent_iter, &bits, 1 );
1034 : : #endif // MB_VTK_MATERIAL_SETS
1035 [ # # ][ # # ]: 0 : result = mdbImpl->tag_set_data( handle, &*ent_iter, 1, &bits );
1036 [ # # ]: 0 : if( MB_SUCCESS != result )
1037 : : {
1038 [ # # ]: 0 : delete[] data;
1039 : 0 : return result;
1040 : : }
1041 : : }
1042 [ # # ]: 0 : delete[] data;
1043 : : }
1044 : : }
1045 [ + - ][ + + ]: 26 : else if( ( type >= 2 && type <= 9 ) || type == 12 )
[ - + ]
1046 : : {
1047 [ + - ]: 14 : std::vector< int > data;
1048 [ + - ][ + - ]: 36 : for( iter = entities.begin(); iter != entities.end(); ++iter )
[ + + ][ + - ]
1049 : : {
1050 [ + - ][ + - ]: 22 : data.resize( iter->size() * per_elem );
[ + - ]
1051 [ + - ][ + - ]: 22 : if( !tokens.get_integers( iter->size() * per_elem, &data[0] ) ) return MB_FAILURE;
[ + - ][ + - ]
[ - + ]
1052 : : #ifdef MB_VTK_MATERIAL_SETS
1053 : : if( isMaterial ) materialMap.add_entities( *iter, (unsigned char*)&data[0], per_elem * size );
1054 : : #endif // MB_VTK_MATERIAL_SETS
1055 [ + - ][ + - ]: 22 : result = mdbImpl->tag_set_data( handle, *iter, &data[0] );
[ + - ]
1056 [ - + ]: 22 : if( MB_SUCCESS != result ) return result;
1057 : 14 : }
1058 : : }
1059 [ + - ][ + - ]: 12 : else if( type == 10 || type == 11 )
1060 : : {
1061 [ + - ]: 12 : std::vector< double > data;
1062 [ + - ][ + - ]: 24 : for( iter = entities.begin(); iter != entities.end(); ++iter )
[ + + ][ + - ]
1063 : : {
1064 [ + - ][ + - ]: 12 : data.resize( iter->size() * per_elem );
[ + - ]
1065 [ + - ][ + - ]: 12 : if( !tokens.get_doubles( iter->size() * per_elem, &data[0] ) ) return MB_FAILURE;
[ + - ][ + - ]
[ - + ]
1066 : : #ifdef MB_VTK_MATERIAL_SETS
1067 : : if( isMaterial ) materialMap.add_entities( *iter, (unsigned char*)&data[0], per_elem * size );
1068 : : #endif // MB_VTK_MATERIAL_SETS
1069 [ + - ][ + - ]: 12 : result = mdbImpl->tag_set_data( handle, *iter, &data[0] );
[ + - ]
1070 [ - + ]: 12 : if( MB_SUCCESS != result ) return result;
1071 : 12 : }
1072 : : }
1073 : :
1074 : 26 : return MB_SUCCESS;
1075 : : }
1076 : :
1077 : 22 : ErrorCode ReadVtk::vtk_read_scalar_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
1078 : : {
1079 [ + - ]: 22 : int type = tokens.match_token( vtk_type_names );
1080 [ - + ]: 22 : if( !type ) return MB_FAILURE;
1081 : :
1082 : : long size;
1083 [ + - ]: 22 : const char* tok = tokens.get_string();
1084 [ - + ]: 22 : if( !tok ) return MB_FAILURE;
1085 : :
1086 : 22 : const char* end = 0;
1087 : 22 : size = strtol( tok, (char**)&end, 0 );
1088 [ - + ]: 22 : if( *end )
1089 : : {
1090 : 0 : size = 1;
1091 [ # # ]: 0 : tokens.unget_token();
1092 : : }
1093 : :
1094 : : // VTK spec says cannot be greater than 4--do we care?
1095 [ - + ]: 22 : if( size < 1 )
1096 : : { //|| size > 4)
1097 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Scalar count out of range [1,4] at line " << tokens.line_number() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1098 : : }
1099 : :
1100 [ + - ][ + - ]: 22 : if( !tokens.match_token( "LOOKUP_TABLE" ) || !tokens.match_token( "default" ) ) return MB_FAILURE;
[ + - ][ - + ]
[ - + ]
1101 : :
1102 [ + - ]: 22 : return vtk_read_tag_data( tokens, type, size, entities, name );
1103 : : }
1104 : :
1105 : 0 : ErrorCode ReadVtk::vtk_read_color_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
1106 : : {
1107 : : long size;
1108 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 1, &size ) || size < 1 ) return MB_FAILURE;
[ # # ][ # # ]
1109 : :
1110 [ # # ]: 0 : return vtk_read_tag_data( tokens, 10, size, entities, name );
1111 : : }
1112 : :
1113 : 4 : ErrorCode ReadVtk::vtk_read_vector_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
1114 : : {
1115 : 4 : int type = tokens.match_token( vtk_type_names );
1116 [ - + ]: 4 : if( !type ) return MB_FAILURE;
1117 : :
1118 : 4 : return vtk_read_tag_data( tokens, type, 3, entities, name );
1119 : : }
1120 : :
1121 : 0 : ErrorCode ReadVtk::vtk_read_texture_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
1122 : : {
1123 : : int type, dim;
1124 [ # # ][ # # ]: 0 : if( !tokens.get_integers( 1, &dim ) || !( type = tokens.match_token( vtk_type_names ) ) ) return MB_FAILURE;
[ # # ][ # # ]
[ # # ]
1125 : :
1126 [ # # ][ # # ]: 0 : if( dim < 1 || dim > 3 )
1127 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Invalid dimension (" << dim << ") at line " << tokens.line_number() ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1128 : :
1129 [ # # ]: 0 : return vtk_read_tag_data( tokens, type, dim, entities, name );
1130 : : }
1131 : :
1132 : 0 : ErrorCode ReadVtk::vtk_read_tensor_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
1133 : : {
1134 : 0 : int type = tokens.match_token( vtk_type_names );
1135 [ # # ]: 0 : if( !type ) return MB_FAILURE;
1136 : :
1137 : 0 : return vtk_read_tag_data( tokens, type, 9, entities, name );
1138 : : }
1139 : :
1140 : 0 : ErrorCode ReadVtk::vtk_read_field_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* )
1141 : : {
1142 : : long num_fields;
1143 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 1, &num_fields ) ) return MB_FAILURE;
1144 : :
1145 : : long i;
1146 [ # # ]: 0 : for( i = 0; i < num_fields; ++i )
1147 : : {
1148 [ # # ]: 0 : const char* tok = tokens.get_string();
1149 [ # # ]: 0 : if( !tok ) return MB_FAILURE;
1150 : :
1151 [ # # ]: 0 : std::string name_alloc( tok );
1152 : :
1153 : : long num_comp;
1154 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 1, &num_comp ) ) return MB_FAILURE;
1155 : :
1156 : : long num_tuples;
1157 [ # # ][ # # ]: 0 : if( !tokens.get_long_ints( 1, &num_tuples ) ) return MB_FAILURE;
1158 : :
1159 [ # # ]: 0 : int type = tokens.match_token( vtk_type_names );
1160 [ # # ]: 0 : if( !type ) return MB_FAILURE;
1161 : :
1162 [ # # ][ # # ]: 0 : ErrorCode result = vtk_read_tag_data( tokens, type, num_comp, entities, name_alloc.c_str() );MB_CHK_SET_ERR( result, "Error reading data for field \"" << name_alloc << "\" (" << num_comp << " components, "
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1163 : : << num_tuples << " tuples, type " << type
1164 : : << ") at line " << tokens.line_number() );
1165 : 0 : }
1166 : :
1167 : 0 : return MB_SUCCESS;
1168 : : }
1169 : :
1170 : 0 : ErrorCode ReadVtk::store_file_ids( Tag tag, const Range& verts, const std::vector< Range >& elems )
1171 : : {
1172 : : ErrorCode rval;
1173 : :
1174 : 0 : rval = readMeshIface->assign_ids( tag, verts );
1175 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
1176 : :
1177 : 0 : int id = 0;
1178 [ # # ]: 0 : for( size_t i = 0; i < elems.size(); ++i )
1179 : : {
1180 : 0 : rval = readMeshIface->assign_ids( tag, elems[i], id );
1181 : 0 : id += elems[i].size();
1182 : : }
1183 : :
1184 : 0 : return MB_SUCCESS;
1185 : : }
1186 : :
1187 [ + - ][ + - ]: 228 : } // namespace moab
|