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 : : #ifdef WIN32
17 : : #ifdef _DEBUG
18 : : // turn off warnings that say they debugging identifier has been truncated
19 : : // this warning comes up when using some STL containers
20 : : #pragma warning( disable : 4786 )
21 : : #endif
22 : : #endif
23 : :
24 : : #include "WriteVtk.hpp"
25 : : #include "moab/VtkUtil.hpp"
26 : : #include "SysUtil.hpp"
27 : :
28 : : #include <fstream>
29 : : #include <iostream>
30 : : #include <stdio.h>
31 : : #include <assert.h>
32 : : #include <vector>
33 : : #include <set>
34 : : #include <map>
35 : : #include <iterator>
36 : :
37 : : #include "moab/Interface.hpp"
38 : : #include "moab/Range.hpp"
39 : : #include "moab/CN.hpp"
40 : : #include "MBTagConventions.hpp"
41 : : #include "moab/WriteUtilIface.hpp"
42 : : #include "Internals.hpp"
43 : : #include "moab/FileOptions.hpp"
44 : :
45 : : #define INS_ID( stringvar, prefix, id ) sprintf( stringvar, prefix, id )
46 : :
47 : : namespace moab
48 : : {
49 : :
50 : : const int DEFAULT_PRECISION = 10;
51 : : const bool DEFAULT_STRICT = true;
52 : :
53 : 4 : WriterIface* WriteVtk::factory( Interface* iface )
54 : : {
55 [ + - ]: 4 : return new WriteVtk( iface );
56 : : }
57 : :
58 : 4 : WriteVtk::WriteVtk( Interface* impl )
59 : 4 : : mbImpl( impl ), writeTool( 0 ), mStrict( DEFAULT_STRICT ), freeNodes( 0 ), createOneNodeCells( false )
60 : : {
61 [ - + ]: 4 : assert( impl != NULL );
62 [ + - ]: 4 : impl->query_interface( writeTool );
63 : 4 : }
64 : :
65 : 12 : WriteVtk::~WriteVtk()
66 : : {
67 : 4 : mbImpl->release_interface( writeTool );
68 [ - + ]: 8 : }
69 : :
70 : 4 : ErrorCode WriteVtk::write_file( const char* file_name, const bool overwrite, const FileOptions& opts,
71 : : const EntityHandle* output_list, const int num_sets,
72 : : const std::vector< std::string >& /* qa_list */, const Tag* tag_list, int num_tags,
73 : : int /* export_dimension */ )
74 : : {
75 : : ErrorCode rval;
76 : :
77 : : // Get precision for node coordinates
78 : : int precision;
79 [ + - ][ + - ]: 4 : if( MB_SUCCESS != opts.get_int_option( "PRECISION", precision ) ) precision = DEFAULT_PRECISION;
80 : :
81 [ + - ][ - + ]: 4 : if( MB_SUCCESS == opts.get_null_option( "STRICT" ) )
82 : 0 : mStrict = true;
83 [ + - ][ - + ]: 4 : else if( MB_SUCCESS == opts.get_null_option( "RELAXED" ) )
84 : 0 : mStrict = false;
85 : : else
86 : 4 : mStrict = DEFAULT_STRICT;
87 : :
88 [ + - ][ - + ]: 4 : if( MB_SUCCESS == opts.get_null_option( "CREATE_ONE_NODE_CELLS" ) ) createOneNodeCells = true;
89 : :
90 : : // Get entities to write
91 [ + - ][ + - ]: 8 : Range nodes, elems;
92 [ + - ]: 4 : rval = gather_mesh( output_list, num_sets, nodes, elems );
93 [ - + ]: 4 : if( MB_SUCCESS != rval ) return rval;
94 : :
95 : : // Honor overwrite flag
96 [ - + ]: 4 : if( !overwrite )
97 : : {
98 [ # # ]: 0 : rval = writeTool->check_doesnt_exist( file_name );
99 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
100 : : }
101 : :
102 : : // Create file
103 [ + - ][ + - ]: 8 : std::ofstream file( file_name );
104 [ + - ][ - + ]: 4 : if( !file ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Could not open file: " << file_name ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
105 [ + - ]: 4 : file.precision( precision );
106 : :
107 : : // Write file
108 [ + - ][ + - ]: 8 : if( ( rval = write_header( file ) ) != MB_SUCCESS || ( rval = write_nodes( file, nodes ) ) != MB_SUCCESS ||
[ + - ][ + - ]
[ - + ]
109 [ + - ][ + - ]: 4 : ( rval = write_elems( file, nodes, elems ) ) != MB_SUCCESS ||
110 [ + - ][ + - ]: 8 : ( rval = write_tags( file, true, nodes, tag_list, num_tags ) ) != MB_SUCCESS ||
[ + - ][ - + ]
111 : : ( rval = write_tags( file, false, elems, tag_list, num_tags ) ) != MB_SUCCESS )
112 : : {
113 [ # # ]: 0 : file.close();
114 : 0 : remove( file_name );
115 : 0 : return rval;
116 : : }
117 : :
118 : 8 : return MB_SUCCESS;
119 : : }
120 : :
121 : 4 : ErrorCode WriteVtk::gather_mesh( const EntityHandle* set_list, int num_sets, Range& nodes, Range& elems )
122 : : {
123 : : ErrorCode rval;
124 : : int e;
125 : :
126 [ + - ][ - + ]: 4 : if( !set_list || !num_sets )
127 : : {
128 [ # # ]: 0 : Range a;
129 [ # # ]: 0 : rval = mbImpl->get_entities_by_handle( 0, a );
130 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
131 : :
132 [ # # ][ # # ]: 0 : Range::const_iterator node_i, elem_i, set_i;
[ # # ]
133 [ # # ][ # # ]: 0 : node_i = a.lower_bound( a.begin(), a.end(), CREATE_HANDLE( MBVERTEX, 0, e ) );
[ # # ][ # # ]
134 [ # # ][ # # ]: 0 : elem_i = a.lower_bound( node_i, a.end(), CREATE_HANDLE( MBEDGE, 0, e ) );
[ # # ]
135 [ # # ][ # # ]: 0 : set_i = a.lower_bound( elem_i, a.end(), CREATE_HANDLE( MBENTITYSET, 0, e ) );
[ # # ]
136 [ # # ]: 0 : nodes.merge( node_i, elem_i );
137 [ # # ]: 0 : elems.merge( elem_i, set_i );
138 : :
139 : : // Filter out unsupported element types
140 : 0 : EntityType et = MBEDGE;
141 [ # # ][ # # ]: 0 : for( et++; et < MBENTITYSET; et++ )
[ # # ][ # # ]
142 : : {
143 [ # # ][ # # ]: 0 : if( VtkUtil::get_vtk_type( et, CN::VerticesPerEntity( et ) ) ) continue;
[ # # ]
144 [ # # ][ # # ]: 0 : Range::iterator eit = elems.lower_bound( elems.begin(), elems.end(), CREATE_HANDLE( et, 0, e ) ),
[ # # ][ # # ]
145 [ # # ][ # # ]: 0 : ep1it = elems.lower_bound( elems.begin(), elems.end(), CREATE_HANDLE( et + 1, 0, e ) );
[ # # ][ # # ]
146 [ # # ]: 0 : elems.erase( eit, ep1it );
147 : 0 : }
148 : : }
149 : : else
150 : : {
151 [ + - ]: 4 : std::set< EntityHandle > visited;
152 [ + - ][ + - ]: 8 : std::vector< EntityHandle > sets;
153 [ + - ]: 4 : sets.reserve( num_sets );
154 [ + - ][ + - ]: 4 : std::copy( set_list, set_list + num_sets, std::back_inserter( sets ) );
155 [ + + ]: 8 : while( !sets.empty() )
156 : : {
157 : : // Get next set
158 [ + - ]: 4 : EntityHandle set = sets.back();
159 [ + - ]: 4 : sets.pop_back();
160 : : // Skip sets we've already done
161 [ + - ][ - + ]: 4 : if( !visited.insert( set ).second ) continue;
162 : :
163 [ + - ]: 4 : Range a;
164 [ + - ]: 4 : rval = mbImpl->get_entities_by_handle( set, a );
165 [ - + ]: 4 : if( MB_SUCCESS != rval ) return rval;
166 : :
167 [ + - ][ + - ]: 4 : Range::const_iterator node_i, elem_i, set_i;
[ + - ]
168 [ + - ][ + - ]: 4 : node_i = a.lower_bound( a.begin(), a.end(), CREATE_HANDLE( MBVERTEX, 0, e ) );
[ + - ][ + - ]
169 [ + - ][ + - ]: 4 : elem_i = a.lower_bound( node_i, a.end(), CREATE_HANDLE( MBEDGE, 0, e ) );
[ + - ]
170 [ + - ][ + - ]: 4 : set_i = a.lower_bound( elem_i, a.end(), CREATE_HANDLE( MBENTITYSET, 0, e ) );
[ + - ]
171 [ + - ]: 4 : nodes.merge( node_i, elem_i );
172 [ + - ]: 4 : elems.merge( elem_i, set_i );
173 [ + - ][ + - ]: 4 : std::copy( set_i, a.end(), std::back_inserter( sets ) );
[ + - ]
174 : :
175 [ + - ]: 4 : a.clear();
176 [ + - ]: 4 : rval = mbImpl->get_child_meshsets( set, a );
177 [ + - ][ + - ]: 4 : std::copy( a.begin(), a.end(), std::back_inserter( sets ) );
[ + - ][ + - ]
[ + - ]
178 : 4 : }
179 : :
180 [ + - ][ + - ]: 5944 : for( Range::const_iterator ei = elems.begin(); ei != elems.end(); ++ei )
[ + - ][ + - ]
[ + + ][ + - ]
181 : : {
182 [ + - ]: 5940 : std::vector< EntityHandle > connect;
183 [ + - ][ + - ]: 5940 : rval = mbImpl->get_connectivity( &( *ei ), 1, connect );
184 [ - + ]: 5940 : if( MB_SUCCESS != rval ) return rval;
185 : :
186 [ + + ][ + - ]: 28428 : for( unsigned int i = 0; i < connect.size(); ++i )
187 [ + - ][ + - ]: 22488 : nodes.insert( connect[i] );
188 : 5944 : }
189 : : }
190 : :
191 [ + - ][ - + ]: 4 : if( nodes.empty() ) { MB_SET_ERR( MB_ENTITY_NOT_FOUND, "Nothing to write" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
192 : :
193 : 4 : return MB_SUCCESS;
194 : : }
195 : :
196 : 4 : ErrorCode WriteVtk::write_header( std::ostream& stream )
197 : : {
198 : 4 : stream << "# vtk DataFile Version 3.0" << std::endl;
199 : 4 : stream << MOAB_VERSION_STRING << std::endl;
200 : 4 : stream << "ASCII" << std::endl;
201 : 4 : stream << "DATASET UNSTRUCTURED_GRID" << std::endl;
202 : 4 : return MB_SUCCESS;
203 : : }
204 : :
205 : 4 : ErrorCode WriteVtk::write_nodes( std::ostream& stream, const Range& nodes )
206 : : {
207 : : ErrorCode rval;
208 : :
209 [ + - ][ + - ]: 4 : stream << "POINTS " << nodes.size() << " double" << std::endl;
[ + - ][ + - ]
[ + - ]
210 : :
211 : : double coords[3];
212 [ + - ][ + - ]: 5442 : for( Range::const_iterator i = nodes.begin(); i != nodes.end(); ++i )
[ + - ][ + - ]
[ + + ]
213 : : {
214 : 5438 : coords[1] = coords[2] = 0.0;
215 [ + - ][ + - ]: 5438 : rval = mbImpl->get_coords( &( *i ), 1, coords );
216 [ - + ]: 5438 : if( MB_SUCCESS != rval ) return rval;
217 [ + - ][ + - ]: 5438 : stream << coords[0] << ' ' << coords[1] << ' ' << coords[2] << std::endl;
[ + - ][ + - ]
[ + - ][ + - ]
218 : : }
219 : :
220 : 4 : return MB_SUCCESS;
221 : : }
222 : :
223 : 4 : ErrorCode WriteVtk::write_elems( std::ostream& stream, const Range& nodes, const Range& elems )
224 : : {
225 : : ErrorCode rval;
226 : :
227 [ + - ]: 4 : Range connectivity; // because we now support polyhedra, it could contain faces
228 [ + - ][ - + ]: 4 : rval = mbImpl->get_connectivity( elems, connectivity );MB_CHK_ERR( rval );
[ # # ][ # # ]
229 : :
230 [ + - ]: 8 : Range nodes_from_connectivity = connectivity.subset_by_type( MBVERTEX );
231 : : Range faces_from_connectivity =
232 [ + - ]: 8 : subtract( connectivity, nodes_from_connectivity ); // these could be faces of polyhedra
233 : :
234 [ + - ]: 8 : Range connected_nodes;
235 [ + - ][ - + ]: 4 : rval = mbImpl->get_connectivity( faces_from_connectivity, connected_nodes );MB_CHK_ERR( rval );
[ # # ][ # # ]
236 [ + - ]: 4 : connected_nodes.merge( nodes_from_connectivity );
237 : :
238 [ + - ]: 8 : Range free_nodes = subtract( nodes, connected_nodes );
239 : :
240 : : // Get and write counts
241 : : unsigned long num_elems, num_uses;
242 [ + - ]: 4 : num_elems = num_uses = elems.size();
243 : :
244 [ + - ]: 8 : std::map< EntityHandle, int > sizeFieldsPolyhedra;
245 : :
246 [ + - ][ + - ]: 5944 : for( Range::const_iterator i = elems.begin(); i != elems.end(); ++i )
[ + - ][ + - ]
[ + + ]
247 : : {
248 [ + - ][ + - ]: 5940 : EntityType type = mbImpl->type_from_handle( *i );
249 [ + - ][ + - ]: 5940 : if( !VtkUtil::get_vtk_type( type, CN::VerticesPerEntity( type ) ) ) continue;
[ - + ]
250 : :
251 [ + - ]: 5940 : EntityHandle elem = *i;
252 : 5940 : const EntityHandle* connect = NULL;
253 : 5940 : int conn_len = 0;
254 : : // Dummy storage vector for structured mesh "get_connectivity" function
255 [ + - ]: 5940 : std::vector< EntityHandle > storage;
256 [ + - ][ - + ]: 5940 : rval = mbImpl->get_connectivity( elem, connect, conn_len, false, &storage );MB_CHK_ERR( rval );
[ # # ][ # # ]
257 : :
258 : 5940 : num_uses += conn_len;
259 : : // if polyhedra, we will count the number of nodes in each face too
260 [ + - ][ - + ]: 5940 : if( TYPE_FROM_HANDLE( elem ) == MBPOLYHEDRON )
261 : : {
262 : 0 : int numFields = 1; // there will be one for number of faces; forgot about this one
263 [ # # ]: 0 : for( int j = 0; j < conn_len; j++ )
264 : : {
265 : 0 : const EntityHandle* conn = NULL;
266 : 0 : int num_nd = 0;
267 [ # # ][ # # ]: 0 : rval = mbImpl->get_connectivity( connect[j], conn, num_nd );MB_CHK_ERR( rval );
[ # # ][ # # ]
268 : 0 : numFields += num_nd + 1;
269 : : }
270 [ # # ]: 0 : sizeFieldsPolyhedra[elem] = numFields; // will be used later, at writing
271 [ + - ]: 5940 : num_uses += ( numFields - conn_len );
272 : : }
273 : 5940 : }
274 [ + - ]: 4 : freeNodes = (int)free_nodes.size();
275 [ + - ]: 4 : if( !createOneNodeCells ) freeNodes = 0; // do not create one node cells
276 [ + - ][ + - ]: 4 : stream << "CELLS " << num_elems + freeNodes << ' ' << num_uses + 2 * freeNodes << std::endl;
[ + - ][ + - ]
[ + - ]
277 : :
278 : : // Write element connectivity
279 [ + - ]: 8 : std::vector< int > conn_data;
280 [ + - ][ + - ]: 8 : std::vector< unsigned > vtk_types( elems.size() + freeNodes );
281 : 4 : std::vector< unsigned >::iterator t = vtk_types.begin();
282 [ + - ][ + - ]: 5944 : for( Range::const_iterator i = elems.begin(); i != elems.end(); ++i )
[ + - ][ + - ]
[ + + ]
283 : : {
284 : : // Get type information for element
285 [ + - ]: 5940 : EntityHandle elem = *i;
286 [ + - ]: 5940 : EntityType type = TYPE_FROM_HANDLE( elem );
287 : :
288 : : // Get element connectivity
289 : 5940 : const EntityHandle* connect = NULL;
290 : 5940 : int conn_len = 0;
291 : : // Dummy storage vector for structured mesh "get_connectivity" function
292 [ + - ]: 5940 : std::vector< EntityHandle > storage;
293 [ + - ][ - + ]: 5940 : rval = mbImpl->get_connectivity( elem, connect, conn_len, false, &storage );MB_CHK_ERR( rval );
[ # # ][ # # ]
294 : :
295 : : // Get VTK type
296 [ + - ]: 5940 : const VtkElemType* vtk_type = VtkUtil::get_vtk_type( type, conn_len );
297 [ - + ]: 5940 : if( !vtk_type )
298 : : {
299 : : // Try connectivity with 1 fewer node
300 [ # # ]: 0 : vtk_type = VtkUtil::get_vtk_type( type, conn_len - 1 );
301 [ # # ]: 0 : if( vtk_type )
302 : 0 : conn_len--;
303 : : else
304 : : {
305 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Vtk file format does not support elements of type "
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
306 : : << CN::EntityTypeName( type ) << " (" << (int)type << ") with " << conn_len
307 : : << " nodes" );
308 : : }
309 : : }
310 : :
311 : : // Save VTK type index for later
312 [ + - ]: 5940 : *t = vtk_type->vtk_type;
313 [ + - ]: 5940 : ++t;
314 : :
315 [ + - ]: 5940 : if( type != MBPOLYHEDRON )
316 : : {
317 : : // Get IDs from vertex handles
318 [ - + ]: 5940 : assert( conn_len > 0 );
319 [ + - ]: 5940 : conn_data.resize( conn_len );
320 [ + + ]: 28428 : for( int j = 0; j < conn_len; ++j )
321 [ + - ][ + - ]: 22488 : conn_data[j] = nodes.index( connect[j] );
322 : :
323 : : // Write connectivity list
324 [ + - ]: 5940 : stream << conn_len;
325 [ - + ]: 5940 : if( vtk_type->node_order )
326 [ # # ]: 0 : for( int k = 0; k < conn_len; ++k )
327 [ # # ][ # # ]: 0 : stream << ' ' << conn_data[vtk_type->node_order[k]];
[ # # ]
328 : : else
329 [ + + ]: 28428 : for( int k = 0; k < conn_len; ++k )
330 [ + - ][ + - ]: 22488 : stream << ' ' << conn_data[k];
[ + - ]
331 [ + - ]: 5940 : stream << std::endl;
332 : : }
333 : : else
334 : : {
335 : : // POLYHEDRON needs a special case, loop over faces to get nodes
336 [ # # ][ # # ]: 0 : stream << sizeFieldsPolyhedra[elem] << " " << conn_len;
[ # # ][ # # ]
337 [ # # ]: 0 : for( int k = 0; k < conn_len; k++ )
338 : : {
339 : 0 : EntityHandle face = connect[k];
340 : 0 : const EntityHandle* conn = NULL;
341 : 0 : int num_nodes = 0;
342 [ # # ][ # # ]: 0 : rval = mbImpl->get_connectivity( face, conn, num_nodes );MB_CHK_ERR( rval );
[ # # ][ # # ]
343 : : // num_uses += num_nd + 1; // 1 for number of vertices in face
344 [ # # ]: 0 : conn_data.resize( num_nodes );
345 [ # # ]: 0 : for( int j = 0; j < num_nodes; ++j )
346 [ # # ][ # # ]: 0 : conn_data[j] = nodes.index( conn[j] );
347 : :
348 [ # # ][ # # ]: 0 : stream << ' ' << num_nodes;
349 : :
350 [ # # ]: 0 : for( int j = 0; j < num_nodes; ++j )
351 [ # # ][ # # ]: 0 : stream << ' ' << conn_data[j];
[ # # ]
352 : : }
353 [ # # ][ + - ]: 5940 : stream << std::endl;
354 : : }
355 : 5940 : }
356 : :
357 [ - + ]: 4 : if( createOneNodeCells )
358 [ # # ][ # # ]: 0 : for( Range::const_iterator v = free_nodes.begin(); v != free_nodes.end(); ++v, ++t )
[ # # ][ # # ]
[ # # ][ # # ]
359 : : {
360 [ # # ]: 0 : EntityHandle node = *v;
361 [ # # ][ # # ]: 0 : stream << "1 " << nodes.index( node ) << std::endl;
[ # # ][ # # ]
362 [ # # ]: 0 : *t = 1;
363 : : }
364 : :
365 : : // Write element types
366 [ + - ][ + - ]: 4 : stream << "CELL_TYPES " << vtk_types.size() << std::endl;
[ + - ]
367 [ + - ][ + - ]: 5944 : for( std::vector< unsigned >::const_iterator i = vtk_types.begin(); i != vtk_types.end(); ++i )
[ + - ][ + + ]
368 [ + - ][ + - ]: 5940 : stream << *i << std::endl;
[ + - ]
369 : :
370 : 8 : return MB_SUCCESS;
371 : : }
372 : :
373 : 8 : ErrorCode WriteVtk::write_tags( std::ostream& stream, bool nodes, const Range& entities, const Tag* tag_list,
374 : : int num_tags )
375 : : {
376 : : ErrorCode rval;
377 : :
378 : : // The #$%@#$% MOAB interface does not have a function to retrieve
379 : : // all entities with a tag, only all entities with a specified type
380 : : // and tag. Define types to loop over depending on the if vertex
381 : : // or element tag data is being written. It seems horribly inefficient
382 : : // to have the implementation subdivide the results by type and have
383 : : // to call that function once for each type just to recombine the results.
384 : : // Unfortunately, there doesn't seem to be any other way.
385 : : EntityType low_type, high_type;
386 [ + + ]: 8 : if( nodes )
387 : : {
388 : 4 : low_type = MBVERTEX;
389 : 4 : high_type = MBEDGE;
390 : : }
391 : : else
392 : : {
393 : 4 : low_type = MBEDGE;
394 : 4 : high_type = MBENTITYSET;
395 : : }
396 : :
397 : : // Get all defined tags
398 [ + - ]: 8 : std::vector< Tag > tags;
399 : 8 : std::vector< Tag >::iterator i;
400 [ + - ]: 8 : rval = writeTool->get_tag_list( tags, tag_list, num_tags, false );
401 [ - + ]: 8 : if( MB_SUCCESS != rval ) return rval;
402 : :
403 : : // For each tag...
404 : 8 : bool entities_have_tags = false;
405 [ + - ][ + - ]: 88 : for( i = tags.begin(); i != tags.end(); ++i )
[ + + ]
406 : : {
407 : : // Skip tags holding entity handles -- no way to save them
408 : : DataType dtype;
409 [ + - ][ + - ]: 80 : rval = mbImpl->tag_get_data_type( *i, dtype );
410 [ - + ]: 80 : if( MB_SUCCESS != rval ) return rval;
411 [ - + ]: 86 : if( dtype == MB_TYPE_HANDLE ) continue;
412 : :
413 : : // If in strict mode, don't write tags that do not fit in any
414 : : // attribute type (SCALAR : 1 to 4 values, VECTOR : 3 values, TENSOR : 9 values)
415 [ + - ]: 80 : if( mStrict )
416 : : {
417 : : int count;
418 [ + - ][ + - ]: 80 : rval = mbImpl->tag_get_length( *i, count );
419 [ - + ]: 80 : if( MB_SUCCESS != rval ) return rval;
420 [ + - ][ + + ]: 80 : if( count < 1 || ( count > 4 && count != 9 ) ) continue;
[ + - ]
421 : : }
422 : :
423 : : // Get subset of input entities that have the tag set
424 [ + - ]: 74 : Range tagged;
425 [ + - ][ + + ]: 481 : for( EntityType type = low_type; type < high_type; ++type )
426 : : {
427 [ + - ]: 407 : Range tmp_tagged;
428 [ + - ][ + - ]: 407 : rval = mbImpl->get_entities_by_type_and_tag( 0, type, &( *i ), 0, 1, tmp_tagged );
429 [ - + ]: 407 : if( MB_SUCCESS != rval ) return rval;
430 [ + - ][ + - ]: 407 : tmp_tagged = intersect( tmp_tagged, entities );
431 [ + - ][ + - ]: 407 : tagged.merge( tmp_tagged );
432 : 407 : }
433 : :
434 : : // If any entities were tagged
435 [ + - ][ + + ]: 74 : if( !tagged.empty() )
436 : : {
437 : : // If this is the first tag being written for the
438 : : // entity type, write the label marking the beginning
439 : : // of the tag data.
440 [ + + ]: 9 : if( !entities_have_tags )
441 : : {
442 : 3 : entities_have_tags = true;
443 [ - + ]: 3 : if( nodes )
444 [ # # ][ # # ]: 0 : stream << "POINT_DATA " << entities.size() << std::endl;
[ # # ][ # # ]
445 : : else
446 [ + - ][ + - ]: 3 : stream << "CELL_DATA " << entities.size() + freeNodes << std::endl;
[ + - ][ + - ]
447 : : }
448 : :
449 : : // Write the tag
450 [ + - ][ + - ]: 9 : rval = write_tag( stream, *i, entities, tagged );
451 [ - + ][ + - ]: 74 : if( MB_SUCCESS != rval ) return rval;
452 : : }
453 : 74 : }
454 : :
455 : 8 : return MB_SUCCESS;
456 : : }
457 : :
458 : : template < typename T >
459 : 9 : void WriteVtk::write_data( std::ostream& stream, const std::vector< T >& data, unsigned vals_per_tag )
460 : : {
461 : 9 : typename std::vector< T >::const_iterator d = data.begin();
462 : 9 : const unsigned long n = data.size() / vals_per_tag;
463 : :
464 [ # # ][ + + ]: 16965 : for( unsigned long i = 0; i < n; ++i )
[ # # ][ # # ]
465 : : {
466 [ # # ][ # # ]: 33912 : for( unsigned j = 0; j < vals_per_tag; ++j, ++d )
[ + - ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
467 : : {
468 : : if( sizeof( T ) == 1 )
469 [ # # ][ # # ]: 0 : stream << (unsigned int)*d << ' ';
[ # # ]
470 : : else
471 [ # # ][ # # ]: 16956 : stream << *d << ' ';
[ # # ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ]
472 : : }
473 [ # # ][ + - ]: 16956 : stream << std::endl;
[ # # ][ # # ]
474 : : }
475 : 9 : }
476 : :
477 : : // template <>
478 : : // void WriteVtk::write_data<unsigned char>(std::ostream& stream,
479 : : // const std::vector<unsigned char>& data,
480 : : // unsigned vals_per_tag)
481 : : //{
482 : : // std::vector<unsigned char>::const_iterator d = data.begin();
483 : : // const unsigned long n = data.size() / vals_per_tag;
484 : : //
485 : : // for (unsigned long i = 0; i < n; ++i) {
486 : : // for (unsigned j = 0; j < vals_per_tag; ++j, ++d)
487 : : // stream << (unsigned int)*d << ' ';
488 : : // stream << std::endl;
489 : : // }
490 : : //}
491 : :
492 : : template < typename T >
493 : 9 : ErrorCode WriteVtk::write_tag( std::ostream& stream, Tag tag, const Range& entities, const Range& tagged, const int )
494 : : {
495 : : ErrorCode rval;
496 : 9 : int addFreeNodes = 0;
497 [ # # ][ # # ]: 9 : if( TYPE_FROM_HANDLE( entities[0] ) > MBVERTEX ) addFreeNodes = freeNodes;
[ # # ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ]
498 : : // we created freeNodes 1-node cells, so we have to augment cell data too
499 : : // we know that the 1 node cells are added at the end, after all other cells;
500 : : // so the default values will be set to those extra , artificial cells
501 [ # # ][ + - ]: 9 : const unsigned long n = entities.size() + addFreeNodes;
[ # # ]
502 : :
503 : : // Get tag properties
504 : :
505 [ # # ][ + - ]: 9 : std::string name;
[ # # ]
506 : : int vals_per_tag;
507 [ # # ][ # # ]: 9 : if( MB_SUCCESS != mbImpl->tag_get_name( tag, name ) || MB_SUCCESS != mbImpl->tag_get_length( tag, vals_per_tag ) )
[ # # ][ # # ]
[ # # ][ + - ]
[ + - ][ + - ]
[ - + ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
508 : 0 : return MB_FAILURE;
509 : :
510 : : // Get a tag value for each entity. Do this by initializing the
511 : : // "data" vector with zero, and then filling in the values for
512 : : // the entities that actually have the tag set.
513 [ # # ][ + - ]: 18 : std::vector< T > data;
[ # # ]
514 [ # # ][ + - ]: 9 : data.resize( n * vals_per_tag, 0 );
[ # # ]
515 : : // If there is a default value for the tag, set the actual default value
516 [ # # ][ + - ]: 18 : std::vector< T > def_value( vals_per_tag );
[ # # ]
517 [ # # ]: 9 : rval = mbImpl->tag_get_default_value( tag, &( def_value[0] ) );
[ # # + - ]
[ + - # # ]
[ # # ]
518 [ # # ][ # # ]: 9 : if( MB_SUCCESS == rval ) SysUtil::setmem( &( data[0] ), &( def_value[0] ), vals_per_tag * sizeof( T ), n );
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
519 : :
520 [ # # ][ + - ]: 9 : Range::const_iterator t = tagged.begin();
[ # # ]
521 : 9 : typename std::vector< T >::iterator d = data.begin();
522 [ # # ][ # # ]: 16965 : for( Range::const_iterator i = entities.begin(); i != entities.end() && t != tagged.end(); ++i, d += vals_per_tag )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # +
- ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + +
# # # # #
# ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
523 : : {
524 [ # # ][ # # ]: 16956 : if( *i == *t )
[ # # ][ + - ]
[ + - ][ + + ]
[ # # ][ # # ]
[ # # ]
525 : : {
526 [ # # ][ + - ]: 15780 : ++t;
[ # # ]
527 [ # # ][ # # ]: 15780 : rval = mbImpl->tag_get_data( tag, &( *i ), 1, &( *d ) );
[ # # ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ]
528 [ # # ][ - + ]: 15780 : if( MB_SUCCESS != rval ) return rval;
[ # # ]
529 : : }
530 : : }
531 : :
532 : : // Write the tag values, one entity per line.
533 [ # # ][ + - ]: 9 : write_data( stream, data, vals_per_tag );
[ # # ]
534 : :
535 : 18 : return MB_SUCCESS;
536 : : }
537 : :
538 : 0 : ErrorCode WriteVtk::write_bit_tag( std::ostream& stream, Tag tag, const Range& entities, const Range& tagged )
539 : : {
540 : : ErrorCode rval;
541 [ # # ]: 0 : const unsigned long n = entities.size();
542 : :
543 : : // Get tag properties
544 : :
545 [ # # ]: 0 : std::string name;
546 : : int vals_per_tag;
547 [ # # ][ # # ]: 0 : if( MB_SUCCESS != mbImpl->tag_get_name( tag, name ) || MB_SUCCESS != mbImpl->tag_get_length( tag, vals_per_tag ) )
[ # # ][ # # ]
[ # # ]
548 : 0 : return MB_FAILURE;
549 : :
550 [ # # ][ # # ]: 0 : if( vals_per_tag > 8 ) { MB_SET_ERR( MB_FAILURE, "Invalid tag size for bit tag \"" << name << "\"" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
551 : :
552 : : // Get a tag value for each entity.
553 : : // Get bits for each entity and unpack into
554 : : // one integer in the 'data' array for each bit.
555 : : // Initialize 'data' to zero because we will skip
556 : : // those entities for which the tag is not set.
557 [ # # ]: 0 : std::vector< unsigned short > data;
558 [ # # ]: 0 : data.resize( n * vals_per_tag, 0 );
559 [ # # ]: 0 : Range::const_iterator t = tagged.begin();
560 : 0 : std::vector< unsigned short >::iterator d = data.begin();
561 [ # # ][ # # ]: 0 : for( Range::const_iterator i = entities.begin(); i != entities.end() && t != tagged.end(); ++i )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # #
# # ]
562 : : {
563 [ # # ][ # # ]: 0 : if( *i == *t )
[ # # ]
564 : : {
565 [ # # ]: 0 : ++t;
566 : : unsigned char value;
567 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( tag, &( *i ), 1, &value );
568 [ # # ][ # # ]: 0 : for( int j = 0; j < vals_per_tag; ++j, ++d )
569 [ # # ]: 0 : *d = (unsigned short)( value & ( 1 << j ) ? 1 : 0 );
570 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
571 : : }
572 : : else
573 : : {
574 : : // If tag is not set for entity, skip values in array
575 [ # # ]: 0 : d += vals_per_tag;
576 : : }
577 : : }
578 : :
579 : : // Write the tag values, one entity per line.
580 [ # # ]: 0 : write_data( stream, data, vals_per_tag );
581 : :
582 : 0 : return MB_SUCCESS;
583 : : }
584 : :
585 : 9 : ErrorCode WriteVtk::write_tag( std::ostream& s, Tag tag, const Range& entities, const Range& tagged )
586 : : {
587 : : // Get tag properties
588 [ + - ]: 9 : std::string name;
589 : : DataType type;
590 : : int vals_per_tag;
591 [ + - ][ + - ]: 18 : if( MB_SUCCESS != mbImpl->tag_get_name( tag, name ) || MB_SUCCESS != mbImpl->tag_get_length( tag, vals_per_tag ) ||
[ + - ][ + - ]
[ - + ][ - + ]
592 [ + - ]: 9 : MB_SUCCESS != mbImpl->tag_get_data_type( tag, type ) )
593 : 0 : return MB_FAILURE;
594 : :
595 : : // Skip tags of type ENTITY_HANDLE
596 [ - + ]: 9 : if( MB_TYPE_HANDLE == type ) return MB_FAILURE;
597 : :
598 : : // Now that we're past the point where the name would be used in
599 : : // an error message, remove any spaces to conform to VTK file.
600 [ + - ][ + - ]: 105 : for( std::string::iterator i = name.begin(); i != name.end(); ++i )
[ + + ]
601 : : {
602 [ + - ][ + - ]: 96 : if( isspace( *i ) || iscntrl( *i ) ) *i = '_';
[ + - ][ - + ]
[ - + ][ # # ]
603 : : }
604 : :
605 : : // Write the tag description
606 [ - + ][ # # ]: 9 : if( 3 == vals_per_tag && MB_TYPE_DOUBLE == type )
607 [ # # ][ # # ]: 0 : s << "VECTORS " << name << ' ' << VtkUtil::vtkTypeNames[type] << std::endl;
[ # # ][ # # ]
[ # # ]
608 [ - + ]: 9 : else if( 9 == vals_per_tag )
609 [ # # ][ # # ]: 0 : s << "TENSORS " << name << ' ' << VtkUtil::vtkTypeNames[type] << std::endl;
[ # # ][ # # ]
[ # # ]
610 : : else
611 [ + - ][ + - ]: 9 : s << "SCALARS " << name << ' ' << VtkUtil::vtkTypeNames[type] << ' ' << vals_per_tag << std::endl
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
612 [ + - ][ + - ]: 9 : << "LOOKUP_TABLE default" << std::endl;
613 : :
614 : : // Write the tag data
615 [ - + - - : 9 : switch( type )
- ]
616 : : {
617 : : case MB_TYPE_OPAQUE:
618 [ # # ]: 0 : return write_tag< unsigned char >( s, tag, entities, tagged, 0 );
619 : : case MB_TYPE_INTEGER:
620 [ + - ]: 9 : return write_tag< int >( s, tag, entities, tagged, 0 );
621 : : case MB_TYPE_DOUBLE:
622 [ # # ]: 0 : return write_tag< double >( s, tag, entities, tagged, 0 );
623 : : case MB_TYPE_BIT:
624 [ # # ]: 0 : return write_bit_tag( s, tag, entities, tagged );
625 : : default:
626 : 0 : return MB_FAILURE;
627 : 9 : }
628 : : }
629 : :
630 [ + - ][ + - ]: 228 : } // namespace moab
|