Branch data Line data Source code
1 : : #include "ReadTetGen.hpp"
2 : : #include "moab/Interface.hpp"
3 : : #include "moab/Range.hpp"
4 : : #include "moab/ReadUtilIface.hpp"
5 : : #include "moab/FileOptions.hpp"
6 : : #include "MBTagConventions.hpp"
7 : : #include <iostream>
8 : : #include <fstream>
9 : : #include <sstream>
10 : : #include <ctype.h>
11 : : #include <map>
12 : :
13 : : namespace moab
14 : : {
15 : :
16 : 1 : ReaderIface* ReadTetGen::factory( Interface* moab )
17 : : {
18 [ + - ]: 1 : return new ReadTetGen( moab );
19 : : }
20 : :
21 : 2 : ReadTetGen::ReadTetGen( Interface* moab ) : mbIface( moab ), readTool( 0 )
22 : : {
23 [ + - ]: 1 : moab->query_interface( readTool );
24 : 1 : }
25 : :
26 : 3 : ReadTetGen::~ReadTetGen()
27 : : {
28 [ + - ][ + - ]: 1 : if( mbIface && readTool ) mbIface->release_interface( readTool );
29 [ - + ]: 2 : }
30 : :
31 : 1 : ErrorCode ReadTetGen::open_file( const std::string& filename, const std::string& basename, const std::string& suffix,
32 : : const char* exp_suffix, const char* opt_name, const FileOptions& opts,
33 : : std::ifstream& file_stream, bool file_required )
34 : : {
35 [ + - ]: 1 : std::string real_file_name;
36 [ + - ]: 1 : ErrorCode rval = opts.get_option( opt_name, real_file_name );
37 [ - + ][ # # ]: 1 : if( MB_ENTITY_NOT_FOUND == rval || real_file_name.empty() )
[ + - ]
38 : : {
39 [ - + ]: 1 : if( MB_SUCCESS == rval ) file_required = true;
40 [ + - ][ - + ]: 1 : if( suffix == exp_suffix ) { real_file_name = filename; }
[ # # ]
41 : : else
42 : : {
43 [ + - ]: 1 : real_file_name = basename;
44 [ + - ]: 1 : real_file_name += ".";
45 [ + - ]: 1 : real_file_name += exp_suffix;
46 : : }
47 : : }
48 : :
49 [ + - ][ + - ]: 1 : if( !real_file_name.empty() ) file_stream.open( real_file_name.c_str(), std::ios::in );
50 [ + - ][ + - ]: 1 : if( file_required && !file_stream.is_open() )
[ + - ][ + - ]
51 [ + - ][ + - ]: 1 : { MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, real_file_name << ": cannot read file" ); }
[ + - ][ + - ]
[ - + ][ + - ]
52 : :
53 : 1 : return MB_SUCCESS;
54 : : }
55 : :
56 : 0 : ErrorCode ReadTetGen::read_tag_values( const char* /* file_name */, const char* /* tag_name */,
57 : : const FileOptions& /* opts */, std::vector< int >& /* tag_values_out */,
58 : : const SubsetList* /* subset_list */ )
59 : : {
60 : 0 : return MB_NOT_IMPLEMENTED;
61 : : }
62 : :
63 : 1 : ErrorCode ReadTetGen::load_file( const char* file_name_c, const EntityHandle* /* file_set */, const FileOptions& opts,
64 : : const ReaderIface::SubsetList* subset_list, const Tag* file_id_tag )
65 : : {
66 [ + - ][ + - ]: 2 : std::ifstream node_file, ele_file, face_file, edge_file;
[ + - ][ + - ]
67 : : ErrorCode rval;
68 : :
69 [ - + ][ # # ]: 1 : if( subset_list ) { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for TetGen" ); }
[ # # ][ # # ]
[ # # ][ # # ]
70 : :
71 [ + - ][ + - ]: 2 : std::string suffix, base, filename( file_name_c );
[ + - ]
72 : 1 : size_t dot_idx = filename.find_last_of( '.' );
73 [ - + ][ # # ]: 1 : if( dot_idx == std::string::npos ) { base = filename; }
74 : : else
75 : : {
76 [ + - ][ + - ]: 1 : suffix = filename.substr( dot_idx + 1 );
77 [ + + ]: 11 : for( size_t i = 0; i < suffix.length(); ++i )
78 [ + - ][ + - ]: 10 : suffix[i] = (char)tolower( suffix[i] );
79 [ + - ][ + - ]: 1 : if( suffix == "node" || suffix == "ele" || suffix == "face" || suffix == "edge" )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
80 [ # # ][ # # ]: 0 : { base = filename.substr( 0, dot_idx ); }
[ # # ]
81 : : else
82 : : {
83 [ + - ]: 1 : base = filename;
84 : 1 : suffix.clear();
85 : : }
86 : : }
87 : :
88 [ + - ]: 1 : rval = open_file( filename, base, suffix, "node", "NODE_FILE", opts, node_file, true );
89 [ + - ]: 1 : if( MB_SUCCESS != rval ) return rval;
90 [ # # ]: 0 : rval = open_file( filename, base, suffix, "ele", "ELE_FILE", opts, ele_file );
91 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
92 [ # # ]: 0 : rval = open_file( filename, base, suffix, "face", "FACE_FILE", opts, face_file );
93 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
94 [ # # ]: 0 : rval = open_file( filename, base, suffix, "edge", "EDGE_FILE", opts, edge_file );
95 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
96 : :
97 [ # # ][ # # ]: 0 : std::vector< Tag > attr_tags[4];
[ # # ][ # #
# # # # ]
98 [ # # ][ # # ]: 0 : std::vector< int > attr_idx[4];
[ # # ]
[ # # # # ]
99 : 0 : const char* option_names[4] = { "NODE_ATTR_LIST", "EDGE_ATTR_LIST", "TRI_ATTR_LIST", "TET_ATTR_LIST" };
100 : 0 : const char* group_names[4] = { 0, "CURVE_ID", "SURFACE_ID", "VOLUME_ID" };
101 [ # # ]: 0 : for( int i = 0; i < 4; ++i )
102 : : {
103 [ # # ]: 0 : std::string opt_str;
104 [ # # ]: 0 : rval = opts.get_str_option( option_names[i], opt_str );
105 [ # # ]: 0 : if( MB_SUCCESS != rval ) continue;
106 [ # # ]: 0 : rval = parse_attr_list( opt_str, attr_tags[i], attr_idx[i], group_names[i] );
107 [ # # ][ # # ]: 0 : if( MB_SUCCESS != rval ) { MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, option_names[i] << ": invalid option value" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # ]
108 : 0 : }
109 : :
110 [ # # ][ # # ]: 0 : Range tets, tris, edges;
[ # # ]
111 [ # # ]: 0 : std::vector< EntityHandle > nodes;
112 [ # # ][ # # ]: 0 : rval = read_node_file( node_file, &attr_tags[0][0], &attr_idx[0][0], attr_tags[0].size(), nodes );
[ # # ]
113 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval && ele_file.is_open() ) rval = read_elem_file( MBTET, ele_file, nodes, tets );
[ # # ][ # # ]
[ # # ]
114 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval && face_file.is_open() ) rval = read_elem_file( MBTRI, face_file, nodes, tris );
[ # # ][ # # ]
[ # # ]
115 [ # # ][ # # ]: 0 : if( MB_SUCCESS == rval && edge_file.is_open() ) rval = read_elem_file( MBEDGE, edge_file, nodes, edges );
[ # # ][ # # ]
[ # # ]
116 : :
117 [ # # ][ # # ]: 0 : if( file_id_tag && MB_SUCCESS == rval ) rval = readTool->assign_ids( *file_id_tag, &nodes[0], nodes.size() );
[ # # ][ # # ]
118 [ # # ][ # # ]: 0 : if( file_id_tag && MB_SUCCESS == rval ) rval = readTool->assign_ids( *file_id_tag, edges );
[ # # ]
119 [ # # ][ # # ]: 0 : if( file_id_tag && MB_SUCCESS == rval ) rval = readTool->assign_ids( *file_id_tag, tris );
[ # # ]
120 [ # # ][ # # ]: 0 : if( file_id_tag && MB_SUCCESS == rval ) rval = readTool->assign_ids( *file_id_tag, tets );
[ # # ]
121 : :
122 : 1 : return rval;
123 : : }
124 : :
125 : 0 : ErrorCode ReadTetGen::parse_attr_list( const std::string& option_str, std::vector< Tag >& tag_list,
126 : : std::vector< int >& index_list, const char* group_designator )
127 : : {
128 [ # # ]: 0 : std::vector< std::string > name_list;
129 : 0 : size_t prev_pos = 0;
130 [ # # ]: 0 : while( prev_pos != std::string::npos )
131 : : {
132 : 0 : size_t pos = option_str.find_first_of( ',', prev_pos );
133 [ # # ][ # # ]: 0 : name_list.push_back( option_str.substr( prev_pos, pos ) );
134 : 0 : prev_pos = pos + 1;
135 : : }
136 : :
137 [ # # ]: 0 : index_list.resize( name_list.size() );
138 [ # # ]: 0 : std::map< std::string, int > name_count;
139 [ # # ]: 0 : for( size_t i = 0; i < name_list.size(); ++i )
140 [ # # ][ # # ]: 0 : index_list[i] = name_count[name_list[i]]++;
[ # # ]
141 : :
142 [ # # ]: 0 : for( size_t i = 0; i < name_list.size(); ++i )
143 : : {
144 [ # # ][ # # ]: 0 : if( group_designator && name_list[i] == group_designator )
[ # # ][ # # ]
[ # # ]
145 : : {
146 [ # # ]: 0 : tag_list[i] = 0;
147 [ # # ]: 0 : index_list[i] = -1;
148 : : }
149 [ # # ]: 0 : else if( name_list.empty() )
150 : : {
151 [ # # ]: 0 : tag_list[i] = 0;
152 [ # # ]: 0 : index_list[i] = 0;
153 : : }
154 : : else
155 : : {
156 [ # # ][ # # ]: 0 : ErrorCode rval = mbIface->tag_get_handle( name_list[i].c_str(), name_count[name_list[i]], MB_TYPE_DOUBLE,
[ # # ]
157 [ # # ][ # # ]: 0 : tag_list[i], MB_TAG_DENSE | MB_TAG_CREAT );
158 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
159 : : }
160 : : }
161 : :
162 : 0 : return MB_SUCCESS;
163 : : }
164 : :
165 : 0 : ErrorCode ReadTetGen::read_line( std::istream& file, std::string& line, int& lineno )
166 : : {
167 : : // Loop until we find a non-empty line
168 [ # # ]: 0 : do
169 : : {
170 : : // Read a line
171 : 0 : line.clear();
172 [ # # ]: 0 : if( !getline( file, line ) ) return MB_FILE_WRITE_ERROR;
173 : 0 : ++lineno;
174 : : // Strip comments from line
175 : 0 : size_t pos = line.find_first_of( '#' );
176 [ # # ][ # # ]: 0 : if( pos != std::string::npos ) line = line.substr( 0, pos );
177 : : // Strip leading whitespace from line
178 [ # # ][ # # ]: 0 : for( pos = 0; pos < line.length() && isspace( line[pos] ); ++pos )
[ # # ]
179 : : ;
180 [ # # ]: 0 : if( pos == line.length() )
181 : 0 : line.clear();
182 [ # # ]: 0 : else if( pos != 0 )
183 [ # # ]: 0 : line = line.substr( pos );
184 : : } while( line.empty() );
185 : :
186 : 0 : return MB_SUCCESS;
187 : : }
188 : :
189 : 0 : ErrorCode ReadTetGen::read_line( std::istream& file, double* values_out, int num_values, int& lineno )
190 : : {
191 : : // Get a line of text
192 [ # # ]: 0 : std::string line;
193 [ # # ]: 0 : ErrorCode rval = read_line( file, line, lineno );
194 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
195 : :
196 : : // Tokenize line as doubles
197 [ # # ][ # # ]: 0 : std::stringstream str( line );
198 [ # # ]: 0 : for( int i = 0; i < num_values; ++i )
199 : : {
200 : : double v;
201 [ # # ][ # # ]: 0 : if( !( str >> v ) ) { MB_SET_ERR( MB_FAILURE, "Error reading node data at line " << lineno ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
202 : 0 : values_out[i] = v;
203 : : }
204 : :
205 : : // Check that we're at the end of the line
206 : : int junk;
207 [ # # ][ # # ]: 0 : if( ( str >> junk ) || !str.eof() )
[ # # ][ # # ]
[ # # ][ # # ]
208 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Unexpected trailing data for line " << lineno << " of node data" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
209 : :
210 : 0 : return MB_SUCCESS;
211 : : }
212 : :
213 : 0 : ErrorCode ReadTetGen::read_node_file( std::istream& file, const Tag* attr_tag_list, const int* attr_tag_index,
214 : : int attr_tag_list_len, std::vector< EntityHandle >& nodes )
215 : : {
216 : 0 : int lineno = 0;
217 : : ErrorCode rval;
218 : :
219 : : double header_vals[4];
220 [ # # ]: 0 : rval = read_line( file, header_vals, 4, lineno );
221 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
222 : :
223 : 0 : const int num_vtx = (int)header_vals[0];
224 : 0 : const int dim = (int)header_vals[1];
225 : 0 : const int num_attr = (int)header_vals[2];
226 : 0 : const int bdry_flag = (int)header_vals[3];
227 [ # # ][ # # ]: 0 : if( num_vtx < 1 || dim < 2 || dim > 3 || num_attr < 0 || bdry_flag < 0 || bdry_flag > 1 )
[ # # ][ # # ]
[ # # ][ # # ]
228 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Invalid header line for node data" ); }
[ # # ][ # # ]
[ # # ]
229 [ # # ]: 0 : if( attr_tag_list_len > num_attr ) attr_tag_list_len = num_attr;
230 : :
231 : : // Allocate space for tag data
232 [ # # ]: 0 : std::map< Tag, int > tag_size;
233 [ # # ]: 0 : std::map< Tag, std::vector< double > > tag_data;
234 [ # # ]: 0 : for( int i = 0; i < attr_tag_list_len; ++i )
235 : : {
236 [ # # ][ # # ]: 0 : if( !attr_tag_list[i] || attr_tag_index[i] < 0 ) continue;
237 [ # # ]: 0 : std::vector< double >& data = tag_data[attr_tag_list[i]];
238 : : // Increase tag size by one value per vertex for each time
239 : : // we encounter it in the list.
240 [ # # ]: 0 : data.resize( data.size() + num_vtx );
241 [ # # ]: 0 : ++tag_size[attr_tag_list[i]];
242 : : }
243 [ # # ]: 0 : std::vector< double* > attr_data( attr_tag_list_len );
244 [ # # ]: 0 : std::vector< int > attr_size( attr_tag_list_len );
245 [ # # ]: 0 : for( int i = 0; i < attr_tag_list_len; ++i )
246 : : {
247 [ # # ][ # # ]: 0 : if( !attr_tag_list[i] || attr_tag_index[i] < 0 )
248 : : {
249 [ # # ]: 0 : attr_data[i] = 0;
250 [ # # ]: 0 : attr_size[i] = 0;
251 : : }
252 : : else
253 : : {
254 [ # # ][ # # ]: 0 : attr_data[i] = &( tag_data[attr_tag_list[i]] )[0];
[ # # ]
255 [ # # ][ # # ]: 0 : attr_size[i] = tag_size[attr_tag_list[i]];
256 : : }
257 : : }
258 : :
259 : : // Allocate vertices
260 [ # # ]: 0 : std::vector< double* > coords;
261 : : EntityHandle start_handle;
262 [ # # ]: 0 : rval = readTool->get_node_coords( dim, num_vtx, 1, start_handle, coords );
263 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
264 : :
265 : : // Read data line for each node
266 [ # # ]: 0 : nodes.reserve( num_vtx );
267 [ # # ]: 0 : std::vector< double > data( 1 + dim + num_attr + bdry_flag );
268 [ # # ]: 0 : std::vector< int > ids( num_vtx );
269 [ # # ]: 0 : for( int i = 0; i < num_vtx; ++i )
270 : : {
271 [ # # ][ # # ]: 0 : rval = read_line( file, &data[0], data.size(), lineno );
272 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
273 : :
274 : : // Get ID
275 [ # # ][ # # ]: 0 : ids[i] = (int)data[0];
276 [ # # ][ # # ]: 0 : if( ids[i] >= (int)nodes.size() ) nodes.resize( ids[i] + 1 );
[ # # ][ # # ]
277 [ # # ][ # # ]: 0 : nodes[ids[i]] = start_handle + i;
278 : :
279 : : // Get coordinates
280 : : // Cppcheck warning (false positive): variable coords is assigned a value that is never used
281 [ # # ]: 0 : for( int j = 0; j < dim; ++j )
282 [ # # ][ # # ]: 0 : coords[j][i] = data[j + 1];
283 : :
284 : : // Get attribute data
285 [ # # ]: 0 : for( int j = 0; j < attr_tag_list_len; ++j )
286 [ # # ][ # # ]: 0 : if( attr_data[j] ) attr_data[j][i * attr_size[j] + attr_tag_index[j]] = data[j + 1 + dim];
[ # # ][ # # ]
[ # # ]
287 : :
288 : : // Discard boundary bit
289 : : }
290 : :
291 : : // Store tag data
292 [ # # ]: 0 : Range node_range;
293 [ # # ]: 0 : node_range.insert( start_handle, start_handle + num_vtx - 1 );
294 [ # # ][ # # ]: 0 : for( std::map< Tag, std::vector< double > >::iterator i = tag_data.begin(); i != tag_data.end(); ++i )
[ # # ]
295 : : {
296 [ # # ][ # # ]: 0 : rval = mbIface->tag_set_data( i->first, node_range, &i->second[0] );
[ # # ][ # # ]
297 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
298 : : }
299 [ # # ]: 0 : Tag idtag = mbIface->globalId_tag();
300 : :
301 [ # # ][ # # ]: 0 : rval = mbIface->tag_set_data( idtag, node_range, &ids[0] );
302 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
303 : :
304 : 0 : return MB_SUCCESS;
305 : : }
306 : :
307 : 0 : ErrorCode ReadTetGen::read_elem_file( EntityType type, std::istream& file, const std::vector< EntityHandle >& nodes,
308 : : Range& elems )
309 : : {
310 : 0 : int lineno = 0;
311 : : ErrorCode rval;
312 : :
313 : : int node_per_elem, have_group_id, dim;
314 : : double header_vals[3];
315 [ # # # # ]: 0 : switch( type )
316 : : {
317 : : case MBTET:
318 [ # # ]: 0 : rval = read_line( file, header_vals, 3, lineno );
319 : 0 : node_per_elem = (int)header_vals[1];
320 : 0 : have_group_id = (int)header_vals[2];
321 : 0 : dim = 3;
322 : 0 : break;
323 : : case MBTRI:
324 [ # # ]: 0 : rval = read_line( file, header_vals, 2, lineno );
325 : 0 : node_per_elem = 3;
326 : 0 : have_group_id = (int)header_vals[1];
327 : 0 : dim = 2;
328 : 0 : break;
329 : : case MBEDGE:
330 [ # # ]: 0 : rval = read_line( file, header_vals, 1, lineno );
331 : 0 : node_per_elem = 2;
332 : 0 : have_group_id = 0;
333 : 0 : dim = 1;
334 : 0 : break;
335 : : default:
336 : 0 : rval = MB_FAILURE;
337 : 0 : break;
338 : : }
339 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
340 : 0 : const int num_elem = (int)header_vals[0];
341 [ # # ][ # # ]: 0 : if( num_elem < 1 || node_per_elem < 2 || have_group_id < 0 || have_group_id > 1 )
[ # # ][ # # ]
342 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Invalid header line for element data" ); }
[ # # ][ # # ]
[ # # ]
343 : :
344 : : // Create group map
345 [ # # ]: 0 : std::map< double, EntityHandle > groups;
346 : : Tag dim_tag, id_tag;
347 [ # # ]: 0 : id_tag = mbIface->globalId_tag();
348 : :
349 : 0 : const int negone = -1;
350 : : rval = mbIface->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, dim_tag, MB_TAG_SPARSE | MB_TAG_CREAT,
351 [ # # ]: 0 : &negone );
352 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
353 : :
354 : : // Allocate elements
355 : : EntityHandle start_handle, *conn_array;
356 [ # # ]: 0 : rval = readTool->get_element_connect( num_elem, node_per_elem, type, 1, start_handle, conn_array );
357 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
358 [ # # ]: 0 : elems.insert( start_handle, start_handle + num_elem - 1 );
359 : :
360 : : // Read data line for each node
361 [ # # ]: 0 : std::vector< double > data( 1 + node_per_elem + have_group_id );
362 [ # # ]: 0 : std::vector< int > ids( num_elem );
363 [ # # ]: 0 : for( int i = 0; i < num_elem; ++i )
364 : : {
365 [ # # ][ # # ]: 0 : rval = read_line( file, &data[0], data.size(), lineno );
366 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
367 : :
368 : : // Get ID
369 [ # # ][ # # ]: 0 : ids[i] = (int)data[0];
370 : :
371 : : // Get connectivity
372 [ # # ]: 0 : for( int j = 0; j < node_per_elem; ++j )
373 [ # # ][ # # ]: 0 : conn_array[node_per_elem * i + j] = nodes[(int)data[j + 1]];
374 : :
375 : : // Grouping
376 [ # # ][ # # ]: 0 : if( have_group_id && 0.0 != data[node_per_elem + 1] )
[ # # ][ # # ]
377 : : {
378 [ # # ]: 0 : double id = data[node_per_elem + 1];
379 [ # # ]: 0 : EntityHandle grp = groups[id];
380 [ # # ]: 0 : if( 0 == grp )
381 : : {
382 [ # # ]: 0 : rval = mbIface->create_meshset( MESHSET_SET, grp );
383 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
384 [ # # ]: 0 : elems.insert( grp );
385 [ # # ]: 0 : rval = mbIface->tag_set_data( dim_tag, &grp, 1, &dim );
386 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
387 : 0 : int iid = (int)id;
388 [ # # ]: 0 : rval = mbIface->tag_set_data( id_tag, &grp, 1, &iid );
389 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
390 [ # # ]: 0 : groups[id] = grp;
391 : : }
392 : 0 : EntityHandle handle = start_handle + i;
393 [ # # ]: 0 : rval = mbIface->add_entities( grp, &handle, 1 );
394 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
395 : : }
396 : : }
397 : :
398 : : // Store id data
399 [ # # ]: 0 : Range elems2;
400 [ # # ]: 0 : elems2.insert( start_handle, start_handle + num_elem - 1 );
401 [ # # ][ # # ]: 0 : rval = mbIface->tag_set_data( id_tag, elems2, &ids[0] );
402 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
403 : :
404 : 0 : return MB_SUCCESS;
405 : : }
406 : :
407 [ + - ][ + - ]: 228 : } // namespace moab
|