LCOV - code coverage report
Current view: top level - src/io - WriteVtk.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 210 292 71.9 %
Date: 2020-12-16 07:07:30 Functions: 14 20 70.0 %
Branches: 330 1185 27.8 %

           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

Generated by: LCOV version 1.11