1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
 * storing and accessing finite element mesh data.
 *
 * Copyright 2004 Sandia Corporation.  Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
 * retains certain rights in this software.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 */

#ifdef WIN32
#ifdef _DEBUG
// turn off warnings that say they debugging identifier has been truncated
// this warning comes up when using some STL containers
#pragma warning( disable : 4786 )
#endif
#endif

#include "WriteSmf.hpp"

#include <fstream>
#include <iostream>
#include <cstdio>
#include <cassert>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>

#include "moab/Interface.hpp"
#include "moab/Range.hpp"
#include "moab/CN.hpp"
#include "MBTagConventions.hpp"
#include "moab/WriteUtilIface.hpp"
#include "Internals.hpp"
#include "moab/FileOptions.hpp"

namespace moab
{

const int DEFAULT_PRECISION = 10;
// const bool DEFAULT_STRICT = true;

WriterIface* WriteSmf::factory( Interface* iface )
{
    return new WriteSmf( iface );
}

WriteSmf::WriteSmf( Interface* impl ) : mbImpl( impl ), writeTool( 0 )
{
    assert( impl != NULL );
    impl->query_interface( writeTool );
}

WriteSmf::~WriteSmf()
{
    mbImpl->release_interface( writeTool );
}

ErrorCode WriteSmf::write_file( const char* file_name,
                                const bool overwrite,
                                const FileOptions& opts,
                                const EntityHandle* output_list,
                                const int num_sets,
                                const std::vector< std::string >& /* qa_list */,
                                const Tag* /* tag_list */,
                                int /* num_tags */,
                                int /* export_dimension */ )
{
    ErrorCode rval;

    // Get precision for node coordinates
    int precision;
    if( MB_SUCCESS != opts.get_int_option( "PRECISION", precision ) ) precision = DEFAULT_PRECISION;

    // Honor overwrite flag
    if( !overwrite )
    {
        rval = writeTool->check_doesnt_exist( file_name );
        if( MB_SUCCESS != rval ) return rval;
    }

    // Create file
    std::ofstream file( file_name );
    if( !file )
    {
        MB_SET_ERR( MB_FILE_WRITE_ERROR, "Could not open file: " << file_name );
    }
    file.precision( precision );

    // Get entities to write
    Range triangles;
    if( !output_list || !num_sets )
    {
        rval = mbImpl->get_entities_by_type( 0, MBTRI, triangles, false );
        if( MB_SUCCESS != rval ) return rval;

        // Somehow get all the nodes from this range, order them, uniquify, then use binary search
    }
    else
    {
        // Get all triangles from output sets
        for( int i = 0; i < num_sets; i++ )
            rval = mbImpl->get_entities_by_type( output_list[i], MBTRI, triangles, false );<--- Variable 'rval' is assigned a value that is never used.
    }
    // Use an array with all the connectivities in the triangles; it will be converted later to ints
    int numTriangles    = triangles.size();
    int array_alloc     = 3 * numTriangles;               // Allocated size of 'array'
    EntityHandle* array = new EntityHandle[array_alloc];  // ptr to working array of result handles
    // Fill up array with node handles; reorder and uniquify
    if( !array ) return MB_MEMORY_ALLOCATION_FAILED;
    int fillA = 0;
    for( Range::const_iterator e = triangles.begin(); e != triangles.end(); ++e )
    {
        const EntityHandle* conn;
        int conn_len;
        rval = mbImpl->get_connectivity( *e, conn, conn_len );
        if( MB_SUCCESS != rval )
        {
            delete[] array;
            return rval;
        }
        if( 3 != conn_len )
        {
            delete[] array;
            return MB_INVALID_SIZE;
        }

        for( int i = 0; i < conn_len; ++i )
            array[fillA++] = conn[i];
    }
    if( fillA != array_alloc )
    {
        delete[] array;
        return MB_INVALID_SIZE;
    }

    std::sort( array, array + array_alloc );
    int numNodes = std::unique( array, array + array_alloc ) - array;

    file << "#$SMF 1.0\n";
    file << "#$vertices " << numNodes << std::endl;
    file << "#$faces " << numTriangles << std::endl;
    file << "# \n";
    file << "# output from MOAB \n";
    file << "# \n";

    // Output first the nodes
    // num nodes??
    // Write the nodes
    double coord[3];
    for( int i = 0; i < numNodes; i++ )
    {
        EntityHandle node_handle = array[i];

        rval = mbImpl->get_coords( &node_handle, 1, coord );
        if( rval != MB_SUCCESS )
        {
            delete[] array;
            return rval;
        }

        file << "v " << coord[0] << " " << coord[1] << " " << coord[2] << std::endl;
    }
    // Write faces now
    // Leave a blank line for cosmetics
    file << " \n";
    for( Range::const_iterator e = triangles.begin(); e != triangles.end(); ++e )
    {
        const EntityHandle* conn;
        int conn_len;
        rval = mbImpl->get_connectivity( *e, conn, conn_len );
        if( MB_SUCCESS != rval )
        {
            delete[] array;
            return rval;
        }
        if( 3 != conn_len )
        {
            delete[] array;
            return MB_INVALID_SIZE;
        }
        file << "f ";
        for( int i = 0; i < conn_len; ++i )
        {
            int indexInArray = std::lower_bound( array, array + numNodes, conn[i] ) - array;
            file << indexInArray + 1 << " ";
        }
        file << std::endl;
    }

    file.close();
    delete[] array;
    return MB_SUCCESS;
}

}  // namespace moab