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 : : #include "AEntityFactory.hpp"
17 : : #include "Internals.hpp"
18 : : #include "moab/Core.hpp"
19 : : #include "moab/Range.hpp"
20 : : #include "moab/Error.hpp"
21 : : #include "moab/CN.hpp"
22 : : #include "moab/MeshTopoUtil.hpp"
23 : : #include "EntitySequence.hpp"
24 : : #include "SequenceData.hpp"
25 : : #include "SequenceManager.hpp"
26 : : #include "RangeSeqIntersectIter.hpp"
27 : :
28 : : #include <assert.h>
29 : : #include <algorithm>
30 : : #include <set>
31 : :
32 : : namespace moab
33 : : {
34 : :
35 : 163487 : ErrorCode AEntityFactory::get_vertices( EntityHandle h, const EntityHandle*& vect_out, int& count_out,
36 : : std::vector< EntityHandle >& storage )
37 : : {
38 : : ErrorCode result;
39 [ + + ]: 163487 : if( MBPOLYHEDRON == TYPE_FROM_HANDLE( h ) )
40 : : {
41 : 12 : storage.clear();
42 : 12 : result = thisMB->get_adjacencies( &h, 1, 0, false, storage );
43 : 12 : vect_out = &storage[0];
44 : 12 : count_out = storage.size();
45 : : }
46 : : else
47 : : {
48 : 163475 : result = thisMB->get_connectivity( h, vect_out, count_out, false, &storage );
49 : : }
50 : 163487 : return result;
51 : : }
52 : :
53 : 438 : AEntityFactory::AEntityFactory( Core* mdb )
54 : : {
55 [ - + ]: 438 : assert( NULL != mdb );
56 : 438 : thisMB = mdb;
57 : 438 : mVertElemAdj = false;
58 : 438 : }
59 : :
60 : 435 : AEntityFactory::~AEntityFactory()
61 : : {
62 : : // clean up all the adjacency information that was created
63 : : EntityType ent_type;
64 : :
65 : : // iterate through each element type
66 [ + + ]: 5655 : for( ent_type = MBVERTEX; ent_type <= MBENTITYSET; ent_type++ )
67 : : {
68 : 5220 : TypeSequenceManager::iterator i;
69 : 5220 : TypeSequenceManager& seqman = thisMB->sequence_manager()->entity_map( ent_type );
70 [ + + ]: 7866 : for( i = seqman.begin(); i != seqman.end(); ++i )
71 : : {
72 : 2646 : std::vector< EntityHandle >** adj_list = ( *i )->data()->get_adjacency_data();
73 [ + + ]: 2646 : if( !adj_list ) continue;
74 : 464 : adj_list += ( *i )->start_handle() - ( *i )->data()->start_handle();
75 : :
76 [ + + ]: 392375 : for( EntityID j = 0; j < ( *i )->size(); ++j )
77 : : {
78 [ + + ]: 391911 : delete adj_list[j];
79 : 391911 : adj_list[j] = 0;
80 : : }
81 : : }
82 : : }
83 : 435 : }
84 : :
85 : : //! get the elements contained by source_entity, of
86 : : //! type target_type, passing back in target_entities; if create_if_missing
87 : : //! is true and no entity is found, one is created; if create_adjacency_option
88 : : //! is >= 0, adjacencies from entities of that dimension to each target_entity
89 : : //! are created (this function uses AEntityFactory::get_element for each element)
90 : 0 : ErrorCode AEntityFactory::get_elements( EntityHandle source_entity, const unsigned int target_dimension,
91 : : std::vector< EntityHandle >& target_entities, const bool create_if_missing,
92 : : const int create_adjacency_option )
93 : : {
94 : : // check for trivial case first
95 : 0 : const EntityType source_type = TYPE_FROM_HANDLE( source_entity );
96 : 0 : const unsigned source_dimension = CN::Dimension( source_type );
97 : :
98 [ # # ][ # # ]: 0 : if( source_type >= MBENTITYSET || target_dimension < 1 || target_dimension > 3 ) { return MB_TYPE_OUT_OF_RANGE; }
[ # # ]
99 [ # # ]: 0 : else if( source_dimension == target_dimension )
100 : : {
101 : 0 : target_entities.push_back( source_entity );
102 : 0 : return MB_SUCCESS;
103 : : }
104 : :
105 : : ErrorCode result;
106 [ # # ]: 0 : if( mVertElemAdj == false )
107 : : {
108 : 0 : result = create_vert_elem_adjacencies();
109 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
110 : : }
111 : :
112 [ # # ]: 0 : if( source_dimension == 0 )
113 : : {
114 : : result = get_zero_to_n_elements( source_entity, target_dimension, target_entities, create_if_missing,
115 : 0 : create_adjacency_option );
116 : : }
117 [ # # ]: 0 : else if( source_dimension > target_dimension )
118 : : {
119 : : result = get_down_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing,
120 : 0 : create_adjacency_option );
121 : : }
122 : : else // if(source_dimension < target_dimension)
123 : : {
124 : : result = get_up_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing,
125 : 0 : create_adjacency_option );
126 : : }
127 : :
128 : 0 : return result;
129 : : }
130 : :
131 : 22 : ErrorCode AEntityFactory::get_polyhedron_vertices( const EntityHandle source_entity,
132 : : std::vector< EntityHandle >& target_entities )
133 : : {
134 : : // get the connectivity array pointer
135 : 22 : const EntityHandle* connect = NULL;
136 : 22 : int num_connect = 0;
137 [ + - ]: 22 : ErrorCode result = thisMB->get_connectivity( source_entity, connect, num_connect );
138 [ - + ]: 22 : if( MB_SUCCESS != result ) return result;
139 : :
140 : : // now get the union of those polygons' vertices
141 [ + - ]: 22 : result = thisMB->get_adjacencies( connect, num_connect, 0, false, target_entities, Interface::UNION );
142 : 22 : return result;
143 : : }
144 : :
145 : 35 : ErrorCode AEntityFactory::get_associated_meshsets( EntityHandle source_entity,
146 : : std::vector< EntityHandle >& target_entities )
147 : : {
148 : :
149 : : ErrorCode result;
150 : :
151 : : const EntityHandle* adj_vec;
152 : : int num_adj;
153 [ + - ]: 35 : result = get_adjacencies( source_entity, adj_vec, num_adj );
154 [ + - ][ + + ]: 35 : if( result != MB_SUCCESS || adj_vec == NULL ) return result;
155 : :
156 : : // find the meshsets in this vector
157 : 31 : DimensionPair dim_pair = CN::TypeDimensionMap[4];
158 : : int dum;
159 : : const EntityHandle* start_ent =
160 [ + - ][ + - ]: 31 : std::lower_bound( adj_vec, adj_vec + num_adj, CREATE_HANDLE( dim_pair.first, MB_START_ID, dum ) );
161 : : const EntityHandle* end_ent =
162 [ + - ][ + - ]: 31 : std::lower_bound( start_ent, adj_vec + num_adj, CREATE_HANDLE( dim_pair.second, MB_END_ID, dum ) );
163 : :
164 : : // copy the the meshsets
165 [ + - ]: 31 : target_entities.insert( target_entities.end(), start_ent, end_ent );
166 : :
167 : 35 : return result;
168 : : }
169 : :
170 : : //! get the element defined by the vertices in vertex_list, of the
171 : : //! type target_type, passing back in target_entity; if create_if_missing
172 : : //! is true and no entity is found, one is created; if create_adjacency_option
173 : : //! is >= 0, adjacencies from entities of that dimension to target_entity
174 : : //! are created (only create_adjacency_option=0 is supported right now,
175 : : //! so that never creates other ancillary entities)
176 : 684211 : ErrorCode AEntityFactory::get_element( const EntityHandle* vertex_list, const int vertex_list_size,
177 : : const EntityType target_type, EntityHandle& target_entity,
178 : : const bool create_if_missing, const EntityHandle source_entity,
179 : : const int /*create_adjacency_option*/ )
180 : : {
181 : :
182 : : // look over nodes to see if this entity already exists
183 : 684211 : target_entity = 0;
184 : : ErrorCode result;
185 : : const EntityHandle *i_adj, *end_adj;
186 : :
187 : : // need vertex adjacencies, so create if necessary
188 [ - + ][ # # ]: 684211 : if( mVertElemAdj == false ) create_vert_elem_adjacencies();
189 : :
190 : : // get the adjacency list
191 : : const EntityHandle* adj_vec;
192 : : int num_adj;
193 [ + - ]: 684211 : result = get_adjacencies( vertex_list[0], adj_vec, num_adj );
194 [ + - ][ - + ]: 684211 : if( result != MB_SUCCESS || adj_vec == NULL ) return result;
195 : :
196 : : // check to see if any of these are equivalent to the vertex list
197 : : int dum;
198 : :
199 : : // use a fixed-size array, for speed; there should never be more than 5 equivalent entities
200 : : EntityHandle temp_vec[15];
201 : 684211 : int temp_vec_size = 0;
202 : :
203 [ + - ][ + - ]: 684211 : i_adj = std::lower_bound( adj_vec, adj_vec + num_adj, CREATE_HANDLE( target_type, MB_START_ID, dum ) );
204 [ + - ][ + - ]: 684211 : end_adj = std::lower_bound( i_adj, adj_vec + num_adj, CREATE_HANDLE( target_type, MB_END_ID, dum ) );
205 [ + + ]: 3595652 : for( ; i_adj != end_adj; ++i_adj )
206 : : {
207 [ + - ][ - + ]: 2911441 : if( TYPE_FROM_HANDLE( *i_adj ) != target_type ) continue;
208 : :
209 [ + - ][ + + ]: 2911441 : if( true == entities_equivalent( *i_adj, vertex_list, vertex_list_size, target_type ) )
210 : 315504 : { temp_vec[temp_vec_size++] = *i_adj; }
211 : : }
212 : :
213 [ + + ][ + + ]: 684211 : if( temp_vec_size == 0 && !create_if_missing ) return result;
214 : :
215 : : // test for size against fixed-size array
216 [ - + ]: 408049 : assert( temp_vec_size <= 15 );
217 : :
218 : : // test for empty first, 'cuz it's cheap
219 [ + + ][ + - ]: 408049 : if( temp_vec_size == 0 && true == create_if_missing )
220 : : {
221 : :
222 : : // Create the element with this handle (handle is a return type and should be the last
223 : : // parameter)
224 [ + - ]: 92630 : result = thisMB->create_element( target_type, vertex_list, vertex_list_size, target_entity );
225 : : }
226 : :
227 : : // next most likely is one entity
228 [ + + ]: 315419 : else if( temp_vec_size == 1 )
229 : 315364 : target_entity = temp_vec[0];
230 : :
231 : : // least likely, most work - leave for last test
232 : : else
233 : : {
234 : : // multiple entities found - look for direct adjacencies
235 [ + + ]: 55 : if( 0 != source_entity )
236 : : {
237 : :
238 : : int num_adjs;
239 [ + - ]: 3 : for( dum = 0; dum < temp_vec_size; dum++ )
240 : : {
241 [ + - ]: 3 : result = get_adjacencies( temp_vec[dum], adj_vec, num_adjs );
242 [ + - ][ + + ]: 3 : if( std::find( adj_vec, ( adj_vec + num_adjs ), source_entity ) != ( adj_vec + num_adjs ) )
243 : : {
244 : : // found it, return it
245 : 2 : target_entity = temp_vec[dum];
246 : 2 : break;
247 : : }
248 : : }
249 : :
250 [ - + ][ # # ]: 2 : if( 0 == target_entity &&
[ - + ]
251 [ # # ][ # # ]: 0 : thisMB->dimension_from_handle( source_entity ) > CN::Dimension( target_type ) + 1 )
252 : : {
253 : : // still have multiple entities, and source dimension is two greater than target,
254 : : // so there may not be any explicit adjacencies between the two; look for common
255 : : // entities of the intermediate dimension
256 [ # # ]: 0 : MeshTopoUtil mtu( thisMB );
257 [ # # ]: 0 : int intermed_dim = CN::Dimension( target_type ) + 1;
258 [ # # ]: 0 : for( dum = 0; dum < temp_vec_size; dum++ )
259 : : {
260 [ # # ][ # # ]: 0 : if( 0 != mtu.common_entity( temp_vec[dum], source_entity, intermed_dim ) )
261 : : {
262 : 0 : target_entity = temp_vec[dum];
263 : 0 : break;
264 : : }
265 : 2 : }
266 : : }
267 : : }
268 : :
269 [ + + ]: 55 : if( target_entity == 0 )
270 : : {
271 : : // if we get here, we didn't find a matching adjacency; just take the first one, but
272 : : // return a non-success result
273 : 53 : target_entity = temp_vec[0];
274 : 53 : result = MB_MULTIPLE_ENTITIES_FOUND;
275 : : }
276 : : }
277 : :
278 : 684211 : return result;
279 : : }
280 : :
281 : 2911441 : bool AEntityFactory::entities_equivalent( const EntityHandle this_entity, const EntityHandle* vertex_list,
282 : : const int vertex_list_size, const EntityType target_type )
283 : : {
284 : : // compare vertices of this_entity with those in the list, returning true if they
285 : : // represent the same element
286 [ + - ]: 2911441 : EntityType this_type = TYPE_FROM_HANDLE( this_entity );
287 : :
288 [ - + ]: 2911441 : if( this_type != target_type )
289 : 0 : return false;
290 : :
291 [ - + ][ # # ]: 2911441 : else if( this_type == MBVERTEX && ( vertex_list_size > 1 || vertex_list[0] != this_entity ) )
[ # # ]
292 : 0 : return false;
293 : :
294 : : // need to compare the actual vertices
295 : 2911441 : const EntityHandle* this_vertices = NULL;
296 : 2911441 : int num_this_vertices = 0;
297 [ + - ]: 2911441 : std::vector< EntityHandle > storage;
298 [ + - ]: 2911441 : thisMB->get_connectivity( this_entity, this_vertices, num_this_vertices, false, &storage );
299 : :
300 : : // see if we can get one node id to match
301 [ - + ]: 2911441 : assert( vertex_list_size > 0 );
302 : : int num_corner_verts =
303 [ + - ]: 2911416 : ( ( this_type == MBPOLYGON || this_type == MBPOLYHEDRON ) ? num_this_vertices
304 [ + + ][ + - ]: 5822857 : : CN::VerticesPerEntity( target_type ) );
305 [ + - ]: 2911441 : const EntityHandle* iter = std::find( this_vertices, ( this_vertices + num_corner_verts ), vertex_list[0] );
306 [ - + ]: 2911441 : if( iter == ( this_vertices + num_corner_verts ) ) return false;
307 : :
308 : : // now lets do connectivity matching
309 : 2911441 : bool they_match = true;
310 : :
311 : : // line up our vectors
312 : : int i;
313 : 2911441 : int offset = iter - this_vertices;
314 : :
315 : : // first compare forward
316 [ + + ]: 3279724 : for( i = 1; i < num_corner_verts; ++i )
317 : : {
318 [ - + ]: 2980786 : if( i >= vertex_list_size )
319 : : {
320 : 0 : they_match = false;
321 : 0 : break;
322 : : }
323 : :
324 [ + + ]: 2980786 : if( vertex_list[i] != this_vertices[( offset + i ) % num_corner_verts] )
325 : : {
326 : 2612503 : they_match = false;
327 : 2612503 : break;
328 : : }
329 : : }
330 : :
331 [ + + ]: 2911441 : if( they_match == true ) return true;
332 : :
333 : 2612503 : they_match = true;
334 : :
335 : : // then compare reverse
336 : : // offset iter to avoid addition inside loop; this just makes sure we don't
337 : : // go off beginning of this_vertices with an index < 0
338 : 2612503 : offset += num_corner_verts;
339 [ + + ]: 2700035 : for( i = 1; i < num_corner_verts; i++ )
340 : : {
341 [ + + ]: 2683469 : if( vertex_list[i] != this_vertices[( offset - i ) % num_corner_verts] )
342 : : {
343 : 2595937 : they_match = false;
344 : 2595937 : break;
345 : : }
346 : : }
347 : 2911441 : return they_match;
348 : : }
349 : :
350 : : //! add an adjacency from from_ent to to_ent; if both_ways is true, add one
351 : : //! in reverse too
352 : : //! NOTE: this function is defined even though we may only be implementing
353 : : //! vertex-based up-adjacencies
354 : 1410354 : ErrorCode AEntityFactory::add_adjacency( EntityHandle from_ent, EntityHandle to_ent, const bool both_ways )
355 : : {
356 [ + - ]: 1410354 : EntityType to_type = TYPE_FROM_HANDLE( to_ent );
357 : :
358 [ - + ]: 1410354 : if( to_type == MBVERTEX ) return MB_ALREADY_ALLOCATED;
359 : :
360 : 1410354 : AdjacencyVector* adj_list_ptr = NULL;
361 [ + - ]: 1410354 : ErrorCode result = get_adjacencies( from_ent, adj_list_ptr, true );
362 [ + + ]: 1410354 : if( MB_SUCCESS != result ) return result;
363 : :
364 : : // get an iterator to the right spot in this sorted vector
365 : 1410310 : AdjacencyVector::iterator adj_iter;
366 [ + + ]: 1410310 : if( !adj_list_ptr->empty() )
367 : : {
368 [ + - ]: 1053722 : adj_iter = std::lower_bound( adj_list_ptr->begin(), adj_list_ptr->end(), to_ent );
369 : :
370 [ + - ][ + + ]: 1053722 : if( adj_iter == adj_list_ptr->end() || to_ent != *adj_iter ) { adj_list_ptr->insert( adj_iter, to_ent ); }
[ + - ][ + + ]
[ + - ][ + + ]
[ + - ][ # # ]
371 : : }
372 : : else
373 [ + - ]: 356588 : adj_list_ptr->push_back( to_ent );
374 : :
375 : : // if both_ways is true, recursively call this function
376 [ + + ][ + - ]: 1410310 : if( true == both_ways && to_type != MBVERTEX ) result = add_adjacency( to_ent, from_ent, false );
[ + - ]
377 : :
378 : 1410354 : return result;
379 : : }
380 : :
381 : : //! remove an adjacency from from the base_entity.
382 : 71920 : ErrorCode AEntityFactory::remove_adjacency( EntityHandle base_entity, EntityHandle adj_to_remove )
383 : : {
384 : : ErrorCode result;
385 : :
386 [ + - ][ + + ]: 71920 : if( TYPE_FROM_HANDLE( base_entity ) == MBENTITYSET )
387 [ + - ]: 100 : return thisMB->remove_entities( base_entity, &adj_to_remove, 1 );
388 : :
389 : : // get the adjacency tag
390 : 71820 : AdjacencyVector* adj_list = NULL;
391 [ + - ]: 71820 : result = get_adjacencies( base_entity, adj_list );
392 [ + + ][ - + ]: 71820 : if( adj_list == NULL || MB_SUCCESS != result ) return result;
393 : :
394 : : // remove the specified entity from the adjacency list and truncate
395 : : // the list to the new length
396 [ + - ][ + - ]: 71811 : adj_list->erase( std::remove( adj_list->begin(), adj_list->end(), adj_to_remove ), adj_list->end() );
397 : :
398 : 71920 : return result;
399 : : }
400 : :
401 : : //! remove all adjacencies from from the base_entity.
402 : 53857 : ErrorCode AEntityFactory::remove_all_adjacencies( EntityHandle base_entity, const bool delete_adj_list )
403 : : {
404 : : ErrorCode result;
405 [ + - ]: 53857 : EntityType base_type = TYPE_FROM_HANDLE( base_entity );
406 : :
407 [ + + ][ + - ]: 53857 : if( base_type == MBENTITYSET ) return thisMB->clear_meshset( &base_entity, 1 );
408 [ + - ]: 24285 : const int base_ent_dim = CN::Dimension( base_type );
409 : :
410 : : // Remove adjacencies from element vertices back to
411 : : // this element. Also check any elements adjacent
412 : : // to the vertex and of higher dimension than this
413 : : // element for downward adjacencies to this element.
414 [ + - ][ + + ]: 24285 : if( vert_elem_adjacencies() && base_type != MBVERTEX )
[ + + ][ + + ]
415 : : {
416 : 23390 : EntityHandle const *connvect = 0, *adjvect = 0;
417 : 23390 : int numconn = 0, numadj = 0;
418 [ + - ]: 23390 : std::vector< EntityHandle > connstorage;
419 [ + - ]: 23390 : result = get_vertices( base_entity, connvect, numconn, connstorage );
420 [ - + ]: 23390 : if( MB_SUCCESS != result ) return result;
421 : :
422 [ + + ][ + - ]: 90143 : for( int i = 0; i < numconn; ++i )
423 : : {
424 [ + - ]: 66753 : result = get_adjacencies( connvect[i], adjvect, numadj );
425 [ - + ]: 66753 : if( MB_SUCCESS != result ) return result;
426 : :
427 : 66753 : bool remove_this = false;
428 [ + + ]: 2544130 : for( int j = 0; j < numadj; ++j )
429 : : {
430 [ + + ]: 2477377 : if( adjvect[j] == base_entity ) remove_this = true;
431 : :
432 [ + - ][ + - ]: 3987750 : if( CN::Dimension( TYPE_FROM_HANDLE( adjvect[j] ) ) != base_ent_dim &&
[ + + ][ - + ]
[ - + ]
433 [ + - ]: 1510373 : explicitly_adjacent( adjvect[j], base_entity ) )
434 [ # # ]: 0 : remove_adjacency( adjvect[j], base_entity );
435 : : }
436 : :
437 [ + - ][ + - ]: 66753 : if( remove_this ) remove_adjacency( connvect[i], base_entity );
438 : 23390 : }
439 : : }
440 : :
441 : : // get the adjacency tag
442 : 24285 : AdjacencyVector* adj_list = 0;
443 [ + - ]: 24285 : result = get_adjacencies( base_entity, adj_list );
444 [ + - ][ + + ]: 24285 : if( MB_SUCCESS != result || !adj_list ) return result;
445 : :
446 : : // check adjacent entities for references back to this entity
447 [ + - ][ + - ]: 621 : for( AdjacencyVector::reverse_iterator it = adj_list->rbegin(); it != adj_list->rend(); ++it )
[ + + ]
448 [ + - ][ + - ]: 101 : remove_adjacency( *it, base_entity );
449 : :
450 [ + - ]: 520 : if( delete_adj_list )
451 [ + - ]: 520 : result = set_adjacency_ptr( base_entity, NULL );
452 : : else
453 : 0 : adj_list->clear();
454 : :
455 : 53857 : return MB_SUCCESS;
456 : : }
457 : :
458 : 185 : ErrorCode AEntityFactory::create_vert_elem_adjacencies()
459 : : {
460 : :
461 : 185 : mVertElemAdj = true;
462 : :
463 : : EntityType ent_type;
464 [ + - ]: 185 : Range::iterator i_range;
465 : : const EntityHandle* connectivity;
466 [ + - ]: 185 : std::vector< EntityHandle > aux_connect;
467 : : int number_nodes;
468 : : ErrorCode result;
469 [ + - ]: 370 : Range handle_range;
470 : :
471 : : // 1. over all element types, for each element, create vertex-element adjacencies
472 [ + - ][ + + ]: 1947 : for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ )
473 : : {
474 [ + - ]: 1806 : handle_range.clear();
475 : :
476 : : // get this type of entity
477 [ + - ]: 1806 : result = thisMB->get_entities_by_type( 0, ent_type, handle_range );
478 [ - + ]: 1806 : if( result != MB_SUCCESS ) return result;
479 : :
480 [ + - ][ + - ]: 141859 : for( i_range = handle_range.begin(); i_range != handle_range.end(); ++i_range )
[ + - ][ + - ]
[ + + ]
481 : : {
482 [ + - ][ + - ]: 140097 : result = get_vertices( *i_range, connectivity, number_nodes, aux_connect );
483 [ - + ]: 140097 : if( MB_SUCCESS != result ) return result;
484 : :
485 : : // add the adjacency
486 [ + + ]: 700307 : for( int k = 0; k < number_nodes; k++ )
487 [ + - ][ + - ]: 560254 : if( ( result = add_adjacency( connectivity[k], *i_range ) ) != MB_SUCCESS ) return result;
[ + + ]
488 : : }
489 : : }
490 : :
491 : 326 : return MB_SUCCESS;
492 : : }
493 : :
494 : 2298523 : ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, const EntityHandle*& adjacent_entities,
495 : : int& num_entities ) const
496 : : {
497 : 2298523 : AdjacencyVector const* vec_ptr = 0;
498 [ + - ]: 2298523 : ErrorCode result = get_adjacency_ptr( entity, vec_ptr );
499 [ + - ][ + + ]: 2298523 : if( MB_SUCCESS != result || !vec_ptr )
500 : : {
501 : 1545645 : adjacent_entities = 0;
502 : 1545645 : num_entities = 0;
503 : 1545645 : return result;
504 : : }
505 : :
506 : 752878 : num_entities = vec_ptr->size();
507 [ + + ][ + - ]: 752878 : adjacent_entities = ( vec_ptr->empty() ) ? NULL : &( ( *vec_ptr )[0] );
508 : 2298523 : return MB_SUCCESS;
509 : : }
510 : :
511 : 343602 : ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, std::vector< EntityHandle >& adjacent_entities ) const
512 : : {
513 : 343602 : AdjacencyVector const* vec_ptr = 0;
514 [ + - ]: 343602 : ErrorCode result = get_adjacency_ptr( entity, vec_ptr );
515 [ + - ][ + + ]: 343602 : if( MB_SUCCESS != result || !vec_ptr )
516 : : {
517 : 275439 : adjacent_entities.clear();
518 : 275439 : return result;
519 : : }
520 : :
521 [ + - ]: 68163 : adjacent_entities = *vec_ptr;
522 : 343602 : return MB_SUCCESS;
523 : : }
524 : :
525 : 2924342 : ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, std::vector< EntityHandle >*& adj_vec, bool create )
526 : : {
527 : 2924342 : adj_vec = 0;
528 : 2924342 : ErrorCode result = get_adjacency_ptr( entity, adj_vec );
529 [ + + ][ + + ]: 2924342 : if( MB_SUCCESS == result && !adj_vec && create )
[ + + ]
530 : : {
531 [ + - ]: 356333 : adj_vec = new AdjacencyVector;
532 : 356333 : result = set_adjacency_ptr( entity, adj_vec );
533 [ - + ]: 356333 : if( MB_SUCCESS != result )
534 : : {
535 [ # # ]: 0 : delete adj_vec;
536 : 0 : adj_vec = 0;
537 : : }
538 : : }
539 : 2924342 : return result;
540 : : }
541 : :
542 : 1502958 : ErrorCode AEntityFactory::get_adjacencies( const EntityHandle source_entity, const unsigned int target_dimension,
543 : : bool create_if_missing, std::vector< EntityHandle >& target_entities )
544 : : {
545 : 1502958 : const EntityType source_type = TYPE_FROM_HANDLE( source_entity );
546 : 1502958 : const unsigned source_dimension = CN::Dimension( source_type );
547 : :
548 : : ErrorCode result;
549 [ + + ]: 1502958 : if( target_dimension == 4 )
550 : : { // get meshsets 'source' is in
551 : 35 : result = get_associated_meshsets( source_entity, target_entities );
552 : : }
553 [ + + ][ + + ]: 1502923 : else if( target_dimension == ( source_type != MBPOLYHEDRON ? 0 : 2 ) )
554 : : {
555 [ + - ]: 260 : std::vector< EntityHandle > tmp_storage;
556 : 260 : const EntityHandle* conn = NULL;
557 : 260 : int len = 0;
558 [ + - ]: 260 : result = thisMB->get_connectivity( source_entity, conn, len, false, &tmp_storage );
559 [ + - ]: 260 : target_entities.insert( target_entities.end(), conn, conn + len );
560 : : }
561 [ + + ][ + - ]: 1502663 : else if( target_dimension == 0 && source_type == MBPOLYHEDRON )
562 : : {
563 : 22 : result = get_polyhedron_vertices( source_entity, target_entities );
564 : : }
565 [ - + ]: 1502641 : else if( source_dimension == target_dimension )
566 : : {
567 : 0 : target_entities.push_back( source_entity );
568 : 0 : result = MB_SUCCESS;
569 : : }
570 : : else
571 : : {
572 [ + + ]: 1502641 : if( mVertElemAdj == false )
573 : : {
574 : 172 : result = create_vert_elem_adjacencies();
575 [ + + ]: 172 : if( MB_SUCCESS != result ) return result;
576 : : }
577 : :
578 [ + + ]: 1502599 : if( source_dimension == 0 )
579 : 1305114 : { result = get_zero_to_n_elements( source_entity, target_dimension, target_entities, create_if_missing ); }
580 [ + + ]: 197485 : else if( source_dimension > target_dimension )
581 : : {
582 : 142352 : result = get_down_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing );
583 : : }
584 : : else // if(source_dimension < target_dimension)
585 : : {
586 : 55133 : result = get_up_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing );
587 : : }
588 : : }
589 : :
590 : 1502958 : return result;
591 : : }
592 : :
593 : 476084 : ErrorCode AEntityFactory::notify_create_entity( const EntityHandle entity, const EntityHandle* node_array,
594 : : const int number_nodes )
595 : : {
596 : 476084 : ErrorCode result = MB_SUCCESS, tmp_result;
597 [ + + ]: 476084 : if( vert_elem_adjacencies() )
598 : : {
599 : : // iterate through nodes and add adjacency information
600 [ + + ]: 172298 : if( TYPE_FROM_HANDLE( entity ) == MBPOLYHEDRON )
601 : : {
602 : : // polyhedron - get real vertex connectivity
603 [ + - ]: 4 : std::vector< EntityHandle > verts;
604 [ + - ]: 4 : tmp_result = get_adjacencies( entity, 0, false, verts );
605 [ - + ]: 4 : if( MB_SUCCESS != tmp_result ) return tmp_result;
606 [ + - ][ + - ]: 20 : for( std::vector< EntityHandle >::iterator vit = verts.begin(); vit != verts.end(); ++vit )
[ + + ][ + - ]
607 : : {
608 [ + - ][ + - ]: 16 : tmp_result = add_adjacency( *vit, entity );
609 [ - + ]: 16 : if( MB_SUCCESS != tmp_result ) result = tmp_result;
610 : 4 : }
611 : : }
612 : : else
613 : : {
614 [ + + ]: 742834 : for( unsigned int i = number_nodes; i--; )
615 : : {
616 : 570536 : tmp_result = add_adjacency( node_array[i], entity );
617 [ - + ]: 570536 : if( MB_SUCCESS != tmp_result ) result = tmp_result;
618 : : }
619 : : }
620 : : }
621 : :
622 : 476084 : return result;
623 : : }
624 : :
625 : 1417832 : ErrorCode AEntityFactory::get_zero_to_n_elements( EntityHandle source_entity, const unsigned int target_dimension,
626 : : std::vector< EntityHandle >& target_entities,
627 : : const bool create_if_missing,
628 : : const int /*create_adjacency_option = -1*/ )
629 : : {
630 : 1417832 : AdjacencyVector::iterator start_ent, end_ent;
631 : :
632 : : // get the adjacency vector
633 : 1417832 : AdjacencyVector* adj_vec = NULL;
634 [ + - ]: 1417832 : ErrorCode result = get_adjacencies( source_entity, adj_vec );
635 [ + - ][ + + ]: 1417832 : if( result != MB_SUCCESS || adj_vec == NULL ) return result;
636 : :
637 [ + + ][ + + ]: 1416542 : if( target_dimension < 3 && create_if_missing )
638 : : {
639 [ + - ]: 3621 : std::vector< EntityHandle > tmp_ents;
640 : :
641 : : start_ent = std::lower_bound( adj_vec->begin(), adj_vec->end(),
642 [ + - ][ + - ]: 3621 : FIRST_HANDLE( CN::TypeDimensionMap[target_dimension + 1].first ) );
643 : :
644 [ + - ][ + - ]: 3621 : end_ent = std::lower_bound( start_ent, adj_vec->end(), LAST_HANDLE( CN::TypeDimensionMap[3].second ) );
645 : :
646 [ + - ]: 7242 : std::vector< EntityHandle > elems( start_ent, end_ent );
647 : :
648 : : // make target_dimension elements from all adjacient higher-dimension elements
649 [ + - ][ + - ]: 26136 : for( start_ent = elems.begin(); start_ent != elems.end(); ++start_ent )
[ + + ]
650 : : {
651 : 22515 : tmp_ents.clear();
652 [ + - ][ + - ]: 22515 : get_down_adjacency_elements( *start_ent, target_dimension, tmp_ents, create_if_missing, 0 );
653 : 3621 : }
654 : : }
655 : :
656 : 1416542 : DimensionPair dim_pair = CN::TypeDimensionMap[target_dimension];
657 [ + - ][ + - ]: 1416542 : start_ent = std::lower_bound( adj_vec->begin(), adj_vec->end(), FIRST_HANDLE( dim_pair.first ) );
658 [ + - ][ + - ]: 1416542 : end_ent = std::lower_bound( start_ent, adj_vec->end(), LAST_HANDLE( dim_pair.second ) );
659 [ + - ]: 1416542 : target_entities.insert( target_entities.end(), start_ent, end_ent );
660 : 1417832 : return MB_SUCCESS;
661 : : }
662 : :
663 : 164867 : ErrorCode AEntityFactory::get_down_adjacency_elements( EntityHandle source_entity, const unsigned int target_dimension,
664 : : std::vector< EntityHandle >& target_entities,
665 : : const bool create_if_missing, const int create_adjacency_option )
666 : : {
667 : :
668 [ + - ]: 164867 : EntityType source_type = TYPE_FROM_HANDLE( source_entity );
669 : :
670 [ + + ][ + + ]: 164867 : if( source_type == MBPOLYHEDRON || source_type == MBPOLYGON )
671 : : return get_down_adjacency_elements_poly( source_entity, target_dimension, target_entities, create_if_missing,
672 [ + - ]: 260 : create_adjacency_option );
673 : :
674 : : // make this a fixed size to avoid cost of working with STL vectors
675 : 164607 : EntityHandle vertex_array[27] = {};
676 : : ErrorCode temp_result;
677 : :
678 : 164607 : const EntityHandle* vertices = NULL;
679 : 164607 : int num_verts = 0;
680 : :
681 : : // I know there are already vertex adjacencies for this - call
682 : : // another function to get them
683 [ + - ]: 164607 : std::vector< EntityHandle > storage;
684 [ + - ]: 164607 : ErrorCode result = thisMB->get_connectivity( source_entity, vertices, num_verts, false, &storage );
685 [ - + ]: 164607 : if( MB_SUCCESS != result ) return result;
686 : :
687 : : int has_mid_nodes[4];
688 [ + - ]: 164607 : CN::HasMidNodes( source_type, num_verts, has_mid_nodes );
689 : :
690 [ + - ]: 329214 : std::vector< int > index_list;
691 [ + - ]: 164607 : int num_sub_ents = CN::NumSubEntities( source_type, target_dimension );
692 : :
693 [ + + ]: 793685 : for( int j = 0; j < num_sub_ents; j++ )
694 : : {
695 : 629078 : const CN::ConnMap& cmap = CN::mConnectivityMap[source_type][target_dimension - 1];
696 : :
697 : 629078 : int verts_per_sub = cmap.num_corners_per_sub_element[j];
698 : :
699 : : // get the corner vertices
700 [ + + ]: 2279334 : for( int i = 0; i < verts_per_sub; i++ )
701 : 1650256 : vertex_array[i] = vertices[cmap.conn[j][i]];
702 : :
703 : : // get the ho nodes for sub-subfacets
704 [ - + ][ # # ]: 629078 : if( has_mid_nodes[1] && target_dimension > 1 )
705 : : {
706 : : // has edge mid-nodes; for each edge, get the right mid-node and put in vertices
707 : : // first get the edge indices
708 : 0 : index_list.clear();
709 [ # # ]: 0 : int int_result = CN::AdjacentSubEntities( source_type, &j, 1, target_dimension, 1, index_list );
710 [ # # ]: 0 : if( 0 != int_result ) return MB_FAILURE;
711 [ # # ]: 0 : for( unsigned int k = 0; k < index_list.size(); k++ )
712 : : {
713 [ # # ][ # # ]: 0 : int tmp_index = CN::HONodeIndex( source_type, num_verts, 1, index_list[k] );
714 [ # # ]: 0 : if( tmp_index >= (int)num_verts ) return MB_INDEX_OUT_OF_RANGE;
715 : :
716 : : // put this vertex on the end; reuse verts_per_sub as an index
717 : 0 : vertex_array[verts_per_sub++] = vertices[tmp_index];
718 : : }
719 : : }
720 : : // get the ho nodes for the target dimension
721 [ - + ]: 629078 : if( has_mid_nodes[target_dimension] )
722 : : {
723 : : // get the ho node index for this subfacet
724 [ # # ]: 0 : int tmp_index = CN::HONodeIndex( source_type, num_verts, target_dimension, j );
725 [ # # ]: 0 : if( tmp_index >= num_verts ) return MB_INDEX_OUT_OF_RANGE;
726 : 0 : vertex_array[verts_per_sub++] = vertices[tmp_index];
727 : : }
728 : :
729 : 629078 : EntityHandle tmp_target = 0;
730 : 629078 : temp_result = get_element( vertex_array, verts_per_sub, cmap.target_type[j], tmp_target, create_if_missing,
731 [ + - ]: 629078 : source_entity, create_adjacency_option );
732 : :
733 [ - + ]: 629078 : if( temp_result != MB_SUCCESS )
734 : 0 : result = temp_result;
735 [ + + ]: 629078 : else if( 0 != tmp_target )
736 [ + - ]: 352916 : target_entities.push_back( tmp_target );
737 : :
738 : : // make sure we're not writing past the end of our fixed-size array
739 [ - + ]: 629078 : if( verts_per_sub > 27 ) return MB_INDEX_OUT_OF_RANGE;
740 : : }
741 : :
742 : 329474 : return result;
743 : : }
744 : :
745 : 260 : ErrorCode AEntityFactory::get_down_adjacency_elements_poly( EntityHandle source_entity,
746 : : const unsigned int target_dimension,
747 : : std::vector< EntityHandle >& target_entities,
748 : : const bool create_if_missing,
749 : : const int /*create_adjacency_option*/ )
750 : : {
751 : :
752 [ + - ]: 260 : EntityType source_type = TYPE_FROM_HANDLE( source_entity );
753 : :
754 [ + + ][ + - ]: 260 : if( !( source_type == MBPOLYHEDRON && target_dimension > 0 && target_dimension < 3 ) &&
[ - + ][ + - ]
755 [ - + ]: 258 : !( source_type == MBPOLYGON && target_dimension == 1 ) )
756 : 0 : return MB_TYPE_OUT_OF_RANGE;
757 : :
758 : : // make this a fixed size to avoid cost of working with STL vectors
759 [ + - ]: 260 : std::vector< EntityHandle > vertex_array;
760 : :
761 : : // I know there are already vertex adjacencies for this - call
762 : : // another function to get them
763 [ + - ]: 260 : ErrorCode result = get_adjacencies( source_entity, 0, false, vertex_array );
764 [ - + ]: 260 : if( MB_SUCCESS != result ) return result;
765 : :
766 : : ErrorCode tmp_result;
767 [ + + ]: 260 : if( source_type == MBPOLYGON )
768 : : {
769 : 258 : result = MB_SUCCESS;
770 : : // put the first vertex on the end so we have a ring
771 [ + - ][ + - ]: 258 : vertex_array.push_back( *vertex_array.begin() );
772 [ + + ]: 1260 : for( unsigned int i = 0; i < vertex_array.size() - 1; i++ )
773 : : {
774 [ + - ][ + - ]: 2004 : Range vrange, adj_edges;
[ + - - ]
775 [ + - ][ + - ]: 1002 : vrange.insert( vertex_array[i] );
776 [ + - ][ + - ]: 1002 : vrange.insert( vertex_array[i + 1] );
777 : : // account for padded polygons; if the vertices are the same, skip
778 [ + - ][ - + ]: 1002 : if( vrange.size() == 1 ) continue;
779 [ + - ]: 1002 : tmp_result = thisMB->get_adjacencies( vrange, 1, false, adj_edges );
780 [ - + ]: 1002 : if( MB_SUCCESS != tmp_result ) result = tmp_result;
781 [ + - ][ + + ]: 1002 : if( adj_edges.size() == 1 )
782 : : {
783 : : // single edge - don't check adjacencies
784 [ + - ][ + - ]: 597 : target_entities.push_back( *adj_edges.begin() );
[ + - ]
785 : : }
786 [ + - ][ - + ]: 405 : else if( adj_edges.size() != 0 )
787 : : {
788 : : // multiple ones - need to check for explicit adjacencies
789 : 0 : unsigned int start_sz = target_entities.size();
790 : : const EntityHandle* explicit_adjs;
791 : : int num_exp;
792 [ # # ][ # # ]: 0 : for( Range::iterator rit = adj_edges.begin(); rit != adj_edges.end(); ++rit )
[ # # ][ # # ]
[ # # ]
793 : : {
794 : : // TODO check return value
795 [ # # ][ # # ]: 0 : this->get_adjacencies( *rit, explicit_adjs, num_exp );
796 [ # # ][ # # ]: 0 : if( NULL != explicit_adjs &&
[ # # ]
797 [ # # ]: 0 : std::find( explicit_adjs, explicit_adjs + num_exp, source_entity ) != explicit_adjs + num_exp )
798 [ # # ][ # # ]: 0 : target_entities.push_back( *rit );
799 : : }
800 [ # # ]: 0 : if( target_entities.size() == start_sz )
801 : : {
802 : 0 : result = MB_MULTIPLE_ENTITIES_FOUND;
803 [ # # ][ # # ]: 0 : target_entities.push_back( *adj_edges.begin() );
[ # # ]
804 : : }
805 : : }
806 : : else
807 : : {
808 : : // we have no adjacent edge yet; we need to create one and also add
809 : : // them to the adjacency of the vertices
810 [ + + ]: 405 : if( create_if_missing )
811 : : {
812 : : EntityHandle newEdge;
813 [ + - ][ + - ]: 401 : EntityHandle v[2] = { vertex_array[i], vertex_array[i + 1] };
814 [ + - ]: 401 : result = thisMB->create_element( MBEDGE, v, 2, newEdge );
815 [ - + ]: 1403 : if( MB_SUCCESS != result ) return result;
[ + - - ]
816 : : // we also need to add explicit adjacency, so next time we do not
817 : : // create again (because we do not find the edge if it is not adjacent to the
818 : : // vertices
819 : : // if (create_adjacency_option >= 0)
820 : : //{
821 [ + - ]: 401 : result = add_adjacency( v[0], newEdge );
822 [ - + ]: 401 : if( MB_SUCCESS != result ) return result;
823 [ + - ]: 401 : result = add_adjacency( v[1], newEdge );
824 [ - + ]: 401 : if( MB_SUCCESS != result ) return result;
825 [ + - ]: 401 : target_entities.push_back( newEdge );
826 : : //}
827 : : }
828 : : }
829 : 1002 : }
830 : 258 : return result;
831 : : }
832 : :
833 : : else
834 : : {
835 [ - + ][ # # ]: 2 : if( target_dimension == 2 ) { result = thisMB->get_connectivity( &source_entity, 1, target_entities ); }
836 : : else
837 : : {
838 [ + - ]: 2 : std::vector< EntityHandle > dum_vec;
839 [ + - ]: 2 : result = thisMB->get_connectivity( &source_entity, 1, dum_vec );
840 [ - + ]: 2 : if( MB_SUCCESS != result ) return result;
841 [ + - ]: 2 : result = thisMB->get_adjacencies( &dum_vec[0], dum_vec.size(), 1, create_if_missing, target_entities,
842 [ + - ]: 2 : Interface::UNION );
843 : 2 : return result;
844 : : }
845 : : }
846 : :
847 : 260 : return MB_SUCCESS;
848 : : }
849 : :
850 : : #if 0
851 : : // Do in-place set intersect of two *sorted* containers.
852 : : // First container is modifed. Second is not.
853 : : // First container must allow assignment through iterators (in practice,
854 : : // must be a container that does not enforce ordering, such
855 : : // as std::vector, std::list, or a c-style array)
856 : : template <typename T1, typename T2>
857 : : static inline T1 intersect( T1 set1_begin, T1 set1_end,
858 : : T2 set2_begin, T2 set2_end )
859 : : {
860 : : T1 set1_write = set1_begin;
861 : : while (set1_begin != set1_end) {
862 : : if (set2_begin == set2_end)
863 : : return set1_write;
864 : : while (*set2_begin < *set1_begin)
865 : : if (++set2_begin == set2_end)
866 : : return set1_write;
867 : : if (!(*set1_begin < *set2_begin)) {
868 : : *set1_write = *set1_begin;
869 : : ++set1_write;
870 : : ++set2_begin;
871 : : }
872 : : ++set1_begin;
873 : : }
874 : : return set1_write;
875 : : }
876 : :
877 : :
878 : : ErrorCode AEntityFactory::get_up_adjacency_elements(
879 : : EntityHandle source_entity,
880 : : const unsigned int target_dimension,
881 : : std::vector<EntityHandle>& target_entities,
882 : : const bool create_if_missing,
883 : : const int option )
884 : : {
885 : : ErrorCode rval;
886 : : const std::vector<EntityHandle> *vtx_adj, *vtx2_adj;
887 : : std::vector<EntityHandle> duplicates;
888 : :
889 : : // Handle ranges
890 : : const size_t in_size = target_entities.size();
891 : : const EntityType src_type = TYPE_FROM_HANDLE(source_entity);
892 : : DimensionPair target_types = CN::TypeDimensionMap[target_dimension];
893 : : const EntityHandle src_beg_handle = CREATE_HANDLE( src_type, 0 );
894 : : const EntityHandle src_end_handle = CREATE_HANDLE( src_type+1, 0 );
895 : : const EntityHandle tgt_beg_handle = CREATE_HANDLE( target_types.first, 0 );
896 : : const EntityHandle tgt_end_handle = CREATE_HANDLE( target_types.second+1, 0 );
897 : :
898 : : // get vertices
899 : : assert(TYPE_FROM_HANDLE(source_entity) != MBPOLYHEDRON); // can't go up from a region
900 : : std::vector<EntityHandle> conn_storage;
901 : : const EntityHandle* conn;
902 : : int conn_len;
903 : : rval = thisMB->get_connectivity( source_entity, conn, conn_len, true, &conn_storage );
904 : : if (MB_SUCCESS != rval)
905 : : return rval;
906 : :
907 : : // shouldn't be here if source entity is not an element
908 : : assert(conn_len > 1);
909 : :
910 : : // create necessary entities. this only makes sense if there exists of a
911 : : // dimension greater than the target dimension.
912 : : if (create_if_missing && target_dimension < 3 && CN::Dimension(src_type) < 2) {
913 : : for (size_t i = 0; i < conn_len; ++i) {
914 : : rval = get_adjacency_ptr( conn[i], vtx_adj );
915 : : if (MB_SUCCESS != rval)
916 : : return rval;
917 : : assert(vtx_adj != NULL); // should contain at least source_entity
918 : :
919 : : std::vector<EntityHandle> tmp2, tmp(*vtx_adj); // copy in case adjacency vector is changed
920 : : for (size_t j = 0; j < tmp.size(); ++j) {
921 : : if (CN::Dimension(TYPE_FROM_HANDLE(tmp[j])) <= (int)target_dimension)
922 : : continue;
923 : : if (TYPE_FROM_HANDLE(tmp[j]) == MBENTITYSET)
924 : : break;
925 : :
926 : : tmp2.clear();
927 : : rval = get_down_adjacency_elements( tmp[j], target_dimension, tmp2, true, option );
928 : : if (MB_SUCCESS != rval)
929 : : return rval;
930 : : }
931 : : }
932 : : }
933 : :
934 : : // get elements adjacent to first vertex
935 : : rval = get_adjacency_ptr( conn[0], vtx_adj );
936 : : if (MB_SUCCESS != rval)
937 : : return rval;
938 : : assert(vtx_adj != NULL); // should contain at least source_entity
939 : : // get elements adjacent to second vertex
940 : : rval = get_adjacency_ptr( conn[1], vtx2_adj );
941 : : if (MB_SUCCESS != rval)
942 : : return rval;
943 : : assert(vtx2_adj != NULL);
944 : :
945 : : // Put intersect of all entities except source entity with
946 : : // the same type as the source entity in 'duplicates'
947 : : std::vector<EntityHandle>::const_iterator it1, it2, end1, end2;
948 : : it1 = std::lower_bound( vtx_adj->begin(), vtx_adj->end(), src_beg_handle );
949 : : it2 = std::lower_bound( vtx2_adj->begin(), vtx2_adj->end(), src_beg_handle );
950 : : end1 = std::lower_bound( it1, vtx_adj->end(), src_end_handle );
951 : : end2 = std::lower_bound( it2, vtx2_adj->end(), src_end_handle );
952 : : assert(end1 != it1); // should at least contain source entity
953 : : duplicates.resize( end1 - it1 - 1 );
954 : : std::vector<EntityHandle>::iterator ins = duplicates.begin();
955 : : for (; it1 != end1; ++it1) {
956 : : if (*it1 != source_entity) {
957 : : *ins = *it1;
958 : : ++ins;
959 : : }
960 : : }
961 : : duplicates.erase( intersect( duplicates.begin(), duplicates.end(), it2, end2 ), duplicates.end() );
962 : :
963 : : // Append to input list any entities of the desired target dimension
964 : : it1 = std::lower_bound( end1, vtx_adj->end(), tgt_beg_handle );
965 : : it2 = std::lower_bound( end2, vtx2_adj->end(), tgt_beg_handle );
966 : : end1 = std::lower_bound( it1, vtx_adj->end(), tgt_end_handle );
967 : : end2 = std::lower_bound( it2, vtx2_adj->end(), tgt_end_handle );
968 : : std::set_intersection( it1, end1, it2, end2, std::back_inserter( target_entities ) );
969 : :
970 : : // for each additional vertex
971 : : for (int i = 2; i < conn_len; ++i) {
972 : : rval = get_adjacency_ptr( conn[i], vtx_adj );
973 : : if (MB_SUCCESS != rval)
974 : : return rval;
975 : : assert(vtx_adj != NULL); // should contain at least source_entity
976 : :
977 : : it1 = std::lower_bound( vtx_adj->begin(), vtx_adj->end(), src_beg_handle );
978 : : end1 = std::lower_bound( it1, vtx_adj->end(), src_end_handle );
979 : : duplicates.erase( intersect( duplicates.begin(), duplicates.end(), it1, end1 ), duplicates.end() );
980 : :
981 : : it1 = std::lower_bound( end1, vtx_adj->end(), tgt_beg_handle );
982 : : end1 = std::lower_bound( it1, vtx_adj->end(), tgt_end_handle );
983 : : target_entities.erase( intersect( target_entities.begin()+in_size, target_entities.end(),
984 : : it1, end1 ), target_entities.end() );
985 : : }
986 : :
987 : : // if no duplicates, we're done
988 : : if (duplicates.empty())
989 : : return MB_SUCCESS;
990 : :
991 : : // Check for explicit adjacencies. If an explicit adjacency
992 : : // connects candidate target entity to an entity equivalent
993 : : // to the source entity, then assume that source entity is *not*
994 : : // adjacent
995 : : const std::vector<EntityHandle>* adj_ptr;
996 : : // check adjacencies from duplicate entities to candidate targets
997 : : for (size_t i = 0; i < duplicates.size(); ++i) {
998 : : rval = get_adjacency_ptr( duplicates[i], adj_ptr );
999 : : if (MB_SUCCESS != rval)
1000 : : return rval;
1001 : : if (!adj_ptr)
1002 : : continue;
1003 : :
1004 : : for (size_t j = 0; j < adj_ptr->size(); ++j) {
1005 : : std::vector<EntityHandle>::iterator k =
1006 : : std::find( target_entities.begin()+in_size, target_entities.end(), (*adj_ptr)[j] );
1007 : : if (k != target_entities.end())
1008 : : target_entities.erase(k);
1009 : : }
1010 : : }
1011 : :
1012 : : // If target dimension is 3 and source dimension is 1, also need to
1013 : : // check for explicit adjacencies to intermediate faces
1014 : : if (CN::Dimension(src_type) > 1 || target_dimension < 3)
1015 : : return MB_SUCCESS;
1016 : :
1017 : : // Get faces adjacent to each element and check for explict
1018 : : // adjacencies from duplicate entities to faces
1019 : : for (size_t i = 0; i < duplicates.size(); ++i) {
1020 : : rval = get_adjacency_ptr( duplicates[i], adj_ptr );
1021 : : if (MB_SUCCESS != rval)
1022 : : return rval;
1023 : : if (!adj_ptr)
1024 : : continue;
1025 : :
1026 : : size_t j;
1027 : : for (j = 0; j < adj_ptr->size(); ++j) {
1028 : : const std::vector<EntityHandle>* adj_ptr2;
1029 : : rval = get_adjacency_ptr( (*adj_ptr)[j], adj_ptr2 );
1030 : : if (MB_SUCCESS != rval)
1031 : : return rval;
1032 : : if (!adj_ptr2)
1033 : : continue;
1034 : :
1035 : : for (size_t k = 0; k < adj_ptr2->size(); ++k) {
1036 : : std::vector<EntityHandle>::iterator it;
1037 : : it = std::find( target_entities.begin()+in_size, target_entities.end(), (*adj_ptr2)[k] );
1038 : : if (it != target_entities.end()) {
1039 : : target_entities.erase(it);
1040 : : j = adj_ptr->size(); // break outer loop
1041 : : break;
1042 : : }
1043 : : }
1044 : : }
1045 : : }
1046 : :
1047 : : return MB_SUCCESS;
1048 : : }
1049 : : #else
1050 : 55133 : ErrorCode AEntityFactory::get_up_adjacency_elements( EntityHandle source_entity, const unsigned int target_dimension,
1051 : : std::vector< EntityHandle >& target_entities,
1052 : : const bool create_if_missing,
1053 : : const int /*create_adjacency_option = -1*/ )
1054 : : {
1055 : :
1056 [ + - ]: 55133 : EntityType source_type = TYPE_FROM_HANDLE( source_entity );
1057 : :
1058 : 55133 : const EntityHandle* source_vertices = NULL;
1059 : 55133 : int num_source_vertices = 0;
1060 [ + - ]: 55133 : std::vector< EntityHandle > conn_storage;
1061 : :
1062 : : // check to see whether there are any equivalent entities (same verts, different entity);
1063 : : // do this by calling get_element with a 0 source_entity, and look for a
1064 : : // MB_MULTIPLE_ENTITIES_FOUND return code
1065 : :
1066 : : // NOTE: we only want corner vertices here, and for the code below which also uses
1067 : : // source_vertices
1068 : : ErrorCode result =
1069 [ + - ]: 55133 : thisMB->get_connectivity( source_entity, source_vertices, num_source_vertices, true, &conn_storage );
1070 [ - + ]: 55133 : if( MB_SUCCESS != result ) return result;
1071 : : EntityHandle temp_entity;
1072 [ + - ]: 55133 : result = get_element( source_vertices, num_source_vertices, source_type, temp_entity, false, 0 );
1073 : :
1074 : 55133 : bool equiv_entities = ( result == MB_MULTIPLE_ENTITIES_FOUND ) ? true : false;
1075 : :
1076 [ + - ]: 110266 : std::vector< EntityHandle > tmp_vec;
1077 [ + + ]: 55133 : if( !equiv_entities )
1078 : : {
1079 : : // get elems adjacent to each node
1080 [ + - ]: 55080 : std::vector< std::vector< EntityHandle > > elems( num_source_vertices );
1081 : : int i;
1082 [ + + ]: 167798 : for( i = 0; i < num_source_vertices; i++ )
1083 : : {
1084 : : // get elements
1085 : : // see comment above pertaining to source_vertices; these are corner vertices only
1086 [ + - ][ + - ]: 112718 : get_zero_to_n_elements( source_vertices[i], target_dimension, elems[i], create_if_missing, 0 );
1087 : : // sort this element list
1088 [ + - ][ + - ]: 112718 : std::sort( elems[i].begin(), elems[i].end() );
[ + - ]
1089 : : }
1090 : :
1091 : : // perform an intersection between all the element lists
1092 : : // see comment above pertaining to source_vertices; these are corner vertices only
1093 [ + + ]: 112718 : for( i = 1; i < num_source_vertices; i++ )
1094 : : {
1095 : 57638 : tmp_vec.clear();
1096 : :
1097 : : // intersection between first list and ith list, put result in tmp
1098 [ + - + - : 230552 : std::set_intersection( elems[0].begin(), elems[0].end(), elems[i].begin(), elems[i].end(),
+ - + - ]
1099 [ + - ][ + - ]: 288190 : std::back_insert_iterator< std::vector< EntityHandle > >( tmp_vec ) );
1100 : : // tmp has elems[0] contents and elems[0] contents has tmp's contents
1101 : : // so that elems[0] always has the intersection of previous operations
1102 [ + - ]: 57638 : elems[0].swap( tmp_vec );
1103 : : }
1104 : :
1105 : : // elems[0] contains the intersection, swap with target_entities
1106 [ + - ][ + - ]: 55080 : target_entities.insert( target_entities.end(), elems[0].begin(), elems[0].end() );
[ + - ]
1107 : : }
1108 [ + + ]: 53 : else if( source_type == MBPOLYGON )
1109 : : {
1110 : : // get adjacencies using polyhedra's connectivity vectors
1111 : : // first get polyhedra neighboring vertices
1112 [ + - ]: 2 : result = thisMB->get_adjacencies( source_vertices, num_source_vertices, 3, false, tmp_vec );
1113 [ - + ]: 2 : if( MB_SUCCESS != result ) return result;
1114 : :
1115 : : // now filter according to whether each is adjacent to the polygon
1116 : 2 : const EntityHandle* connect = NULL;
1117 : 2 : int num_connect = 0;
1118 [ + - ]: 2 : std::vector< EntityHandle > storage;
1119 [ - + ][ + - ]: 2 : for( unsigned int i = 0; i < tmp_vec.size(); i++ )
1120 : : {
1121 [ # # ][ # # ]: 0 : result = thisMB->get_connectivity( tmp_vec[i], connect, num_connect, false, &storage );
1122 [ # # ]: 0 : if( MB_SUCCESS != result ) return result;
1123 [ # # ][ # # ]: 0 : if( std::find( connect, connect + num_connect, source_entity ) != connect + num_connect )
1124 [ # # ][ # # ]: 0 : target_entities.push_back( tmp_vec[i] );
1125 : 2 : }
1126 : : }
1127 : :
1128 : : else
1129 : : {
1130 : : // else get up-adjacencies directly; code copied from get_zero_to_n_elements
1131 : :
1132 : : // get the adjacency vector
1133 : 51 : AdjacencyVector* adj_vec = NULL;
1134 [ + - ]: 51 : result = get_adjacencies( source_entity, adj_vec );
1135 : :
1136 [ - + ]: 51 : if( result != MB_SUCCESS )
1137 : 50 : return result;
1138 [ + + ]: 51 : else if( adj_vec == NULL )
1139 : 50 : return MB_SUCCESS;
1140 : :
1141 [ + - ]: 1 : DimensionPair dim_pair_dp1 = CN::TypeDimensionMap[CN::Dimension( source_type ) + 1],
1142 : 1 : dim_pair_td = CN::TypeDimensionMap[target_dimension];
1143 : : int dum;
1144 : :
1145 [ + - ][ + - ]: 2 : Range tmp_ents, target_ents;
[ + - ]
1146 : :
1147 : : // get iterators for start handle of source_dim+1 and target_dim, and end handle
1148 : : // of target_dim
1149 : : AdjacencyVector::iterator start_ent_dp1 =
1150 : : std::lower_bound( adj_vec->begin(), adj_vec->end(),
1151 [ + - ][ + - ]: 1 : CREATE_HANDLE( dim_pair_dp1.first, MB_START_ID, dum ) ),
1152 : :
1153 : : start_ent_td =
1154 : : std::lower_bound( adj_vec->begin(), adj_vec->end(),
1155 [ + - ][ + - ]: 1 : CREATE_HANDLE( dim_pair_td.first, MB_START_ID, dum ) ),
1156 : :
1157 : : end_ent_td = std::lower_bound( adj_vec->begin(), adj_vec->end(),
1158 [ + - ][ + - ]: 1 : CREATE_HANDLE( dim_pair_td.second, MB_END_ID, dum ) );
1159 : :
1160 : : // get the adjacencies for source_dim+1 to target_dim-1, and the adjacencies from
1161 : : // those to target_dim
1162 [ + - ][ + - ]: 1 : std::copy( start_ent_dp1, start_ent_td, range_inserter( tmp_ents ) );
1163 [ + - ]: 1 : result = thisMB->get_adjacencies( tmp_ents, target_dimension, false, target_ents, Interface::UNION );
1164 [ - + ]: 1 : if( MB_SUCCESS != result ) return result;
1165 : :
1166 : : // now copy the explicit adjacencies to target_dimension
1167 [ + - ][ + - ]: 1 : std::copy( start_ent_td, end_ent_td, range_inserter( target_ents ) );
1168 : :
1169 : : // now insert the whole thing into the argument vector
1170 : : #ifdef MOAB_NO_VECTOR_TEMPLATE_INSERT
1171 : : std::copy( target_ents.begin(), target_ents.end(), std::back_inserter( target_entities ) );
1172 : : #else
1173 [ + - ][ + - ]: 2 : target_entities.insert( target_entities.end(), target_ents.begin(), target_ents.end() );
[ + - ][ + - ]
1174 : : #endif
1175 : : }
1176 : :
1177 : 110216 : return result;
1178 : : }
1179 : : #endif
1180 : :
1181 : 3747 : ErrorCode AEntityFactory::notify_change_connectivity( EntityHandle entity, const EntityHandle* old_array,
1182 : : const EntityHandle* new_array, int number_verts )
1183 : : {
1184 [ + - ]: 3747 : EntityType source_type = TYPE_FROM_HANDLE( entity );
1185 [ - + ]: 3747 : if( source_type == MBPOLYHEDRON ) return MB_NOT_IMPLEMENTED;
1186 : :
1187 : : // find out which ones to add and which to remove
1188 [ + - ][ + - ]: 7494 : std::vector< EntityHandle > old_verts, new_verts;
1189 : : int i;
1190 [ + + ]: 22609 : for( i = 0; i < number_verts; i++ )
1191 : : {
1192 [ + + ]: 18862 : if( old_array[i] != new_array[i] )
1193 : : {
1194 [ + - ]: 11331 : old_verts.push_back( old_array[i] );
1195 [ + - ]: 11331 : new_verts.push_back( new_array[i] );
1196 : : }
1197 : : }
1198 : :
1199 : : ErrorCode result;
1200 : :
1201 [ + + ]: 3747 : if( mVertElemAdj == true )
1202 : : {
1203 : : // update the vertex-entity adjacencies
1204 : 1197 : std::vector< EntityHandle >::iterator adj_iter;
1205 [ + - ][ + - ]: 2488 : for( adj_iter = old_verts.begin(); adj_iter != old_verts.end(); ++adj_iter )
[ + + ]
1206 : : {
1207 [ + - ][ + - ]: 1291 : if( std::find( new_verts.begin(), new_verts.end(), *adj_iter ) == new_verts.end() )
[ + - ][ + + ]
1208 : : {
1209 [ + - ][ + - ]: 1287 : result = remove_adjacency( *adj_iter, entity );
1210 [ - + ]: 1287 : if( MB_SUCCESS != result ) return result;
1211 : : }
1212 : : }
1213 [ + - ][ + - ]: 2488 : for( adj_iter = new_verts.begin(); adj_iter != new_verts.end(); ++adj_iter )
[ + + ]
1214 : : {
1215 [ + - ][ + - ]: 1291 : if( std::find( old_verts.begin(), old_verts.end(), *adj_iter ) == old_verts.end() )
[ + - ][ + + ]
1216 : : {
1217 [ + - ][ + - ]: 1287 : result = add_adjacency( *adj_iter, entity );
1218 [ - + ]: 1287 : if( MB_SUCCESS != result ) return result;
1219 : : }
1220 : : }
1221 : : }
1222 : :
1223 : 7494 : return MB_SUCCESS;
1224 : : }
1225 : :
1226 : : //! return true if 2 entities are explicitly adjacent
1227 : 1510373 : bool AEntityFactory::explicitly_adjacent( const EntityHandle ent1, const EntityHandle ent2 )
1228 : : {
1229 : : const EntityHandle* explicit_adjs;
1230 : : int num_exp;
1231 [ + - ]: 1510373 : get_adjacencies( ent1, explicit_adjs, num_exp );
1232 [ + - ][ - + ]: 1510373 : if( std::find( explicit_adjs, explicit_adjs + num_exp, ent2 ) != explicit_adjs + num_exp )
1233 : 0 : return true;
1234 : : else
1235 : 1510373 : return false;
1236 : : }
1237 : :
1238 : 442 : ErrorCode AEntityFactory::merge_adjust_adjacencies( EntityHandle entity_to_keep, EntityHandle entity_to_remove )
1239 : : {
1240 [ + - ][ + - ]: 442 : int ent_dim = CN::Dimension( TYPE_FROM_HANDLE( entity_to_keep ) );
1241 : : ErrorCode result;
1242 : :
1243 : : // check for newly-formed equivalent entities, and create explicit adjacencies
1244 : : // to distinguish them; this must be done before connectivity of higher-dimensional
1245 : : // entities is changed below, and only needs to be checked if merging vertices
1246 [ + + ]: 442 : if( ent_dim == 0 )
1247 : : {
1248 [ + - ]: 411 : result = check_equiv_entities( entity_to_keep, entity_to_remove );
1249 [ - + ]: 411 : if( MB_SUCCESS != result ) return result;
1250 : : }
1251 : :
1252 : : // check adjacencies TO removed entity
1253 [ + + ]: 472 : for( int dim = 1; dim < ent_dim; dim++ )
1254 : : {
1255 [ + - ]: 30 : Range adjs;
1256 [ + - ]: 30 : result = thisMB->get_adjacencies( &entity_to_remove, 1, dim, false, adjs );
1257 [ - + ]: 30 : if( result != MB_SUCCESS ) return result;
1258 : : // for any explicit ones, make them adjacent to keeper
1259 [ + - ][ # # ]: 30 : for( Range::iterator rit = adjs.begin(); rit != adjs.end(); ++rit )
[ + - ][ + - ]
[ - + ][ + - ]
1260 : : {
1261 [ # # ][ # # ]: 0 : if( this->explicitly_adjacent( *rit, entity_to_remove ) )
[ # # ]
1262 : : {
1263 [ # # ][ # # ]: 0 : result = this->add_adjacency( *rit, entity_to_keep );
1264 [ # # ]: 0 : if( result != MB_SUCCESS ) return result;
1265 : : }
1266 : : }
1267 : 30 : }
1268 : :
1269 : : // check adjacencies FROM removed entity
1270 [ + - ][ + - ]: 884 : std::vector< EntityHandle > conn, adjs;
1271 [ + - ]: 442 : result = this->get_adjacencies( entity_to_remove, adjs );
1272 [ - + ]: 442 : if( result != MB_SUCCESS ) return result;
1273 : : // set them all, and if to_entity is a set, add to that one too
1274 [ + + ]: 1605 : for( unsigned int i = 0; i < adjs.size(); i++ )
1275 : : {
1276 [ + - ][ + - ]: 1163 : if( TYPE_FROM_HANDLE( adjs[i] ) == MBENTITYSET )
[ + + ]
1277 : : {
1278 : : // result = this->add_adjacency(entity_to_keep, adjs[i]);
1279 : : // if(result != MB_SUCCESS) return result;
1280 : : // result = thisMB->add_entities(adjs[i], &entity_to_keep, 1);
1281 : : // if(result != MB_SUCCESS) return result;
1282 [ + - ][ + - ]: 3 : result = thisMB->replace_entities( adjs[i], &entity_to_remove, &entity_to_keep, 1 );
1283 [ - + ]: 3 : if( MB_SUCCESS != result ) return result;
1284 : : }
1285 [ + + ]: 1160 : else if( ent_dim == 0 )
1286 : : {
1287 : 1159 : conn.clear();
1288 [ + - ][ + - ]: 1159 : result = thisMB->get_connectivity( &adjs[i], 1, conn );
1289 : :
1290 [ + - ]: 1159 : if( result == MB_SUCCESS )
1291 : : {
1292 [ + - ]: 1159 : std::replace( conn.begin(), conn.end(), entity_to_remove, entity_to_keep );
1293 [ + - ][ + - ]: 1159 : result = thisMB->set_connectivity( adjs[i], &conn[0], conn.size() );
[ + - ]
1294 [ - + ]: 1159 : if( MB_SUCCESS != result ) return result;
1295 : : }
1296 : : else
1297 : 0 : return result;
1298 : : }
1299 : : else
1300 : : {
1301 [ + - ][ + - ]: 1 : result = this->add_adjacency( entity_to_keep, adjs[i] );
1302 [ - + ]: 1 : if( result != MB_SUCCESS ) return result;
1303 : : }
1304 : : }
1305 : :
1306 : 884 : return MB_SUCCESS;
1307 : : }
1308 : :
1309 : : // check for equivalent entities that may be formed when merging two entities, and
1310 : : // create explicit adjacencies accordingly
1311 : 411 : ErrorCode AEntityFactory::check_equiv_entities( EntityHandle entity_to_keep, EntityHandle entity_to_remove )
1312 : : {
1313 [ + - ][ - + ]: 411 : if( thisMB->dimension_from_handle( entity_to_keep ) > 0 ) return MB_SUCCESS;
1314 : :
1315 : : // get all the adjacencies for both entities for all dimensions > 0
1316 [ + - ][ + - ]: 822 : Range adjs_keep, adjs_remove;
1317 : : ErrorCode result;
1318 : :
1319 [ + + ]: 1644 : for( int dim = 1; dim <= 3; dim++ )
1320 : : {
1321 [ + - ]: 1233 : result = thisMB->get_adjacencies( &entity_to_keep, 1, dim, false, adjs_keep, Interface::UNION );
1322 [ - + ]: 1233 : if( MB_SUCCESS != result ) return result;
1323 [ + - ]: 1233 : result = thisMB->get_adjacencies( &entity_to_remove, 1, dim, false, adjs_remove, Interface::UNION );
1324 [ - + ]: 1233 : if( MB_SUCCESS != result ) return result;
1325 : : }
1326 : :
1327 : : // now look for equiv entities which will be formed
1328 : : // algorithm:
1329 : : // for each entity adjacent to removed entity:
1330 : : EntityHandle two_ents[2];
1331 [ + - ][ + - ]: 1570 : for( Range::iterator rit_rm = adjs_remove.begin(); rit_rm != adjs_remove.end(); ++rit_rm )
[ + - ][ + - ]
[ + + ]
1332 : : {
1333 [ + - ]: 1159 : two_ents[0] = *rit_rm;
1334 : :
1335 : : // - for each entity of same dimension adjacent to kept entity:
1336 [ + - ][ + - ]: 5829 : for( Range::iterator rit_kp = adjs_keep.begin(); rit_kp != adjs_keep.end(); ++rit_kp )
[ + - ][ + - ]
[ + + ]
1337 : : {
1338 [ + - ][ + - ]: 9036 : if( TYPE_FROM_HANDLE( *rit_kp ) != TYPE_FROM_HANDLE( *rit_rm ) ) continue;
[ + - ][ + - ]
[ + + ]
1339 : :
1340 [ + - ]: 4434 : Range all_verts;
1341 [ + - ]: 4434 : two_ents[1] = *rit_kp;
1342 : : // . get union of adjacent vertices to two entities
1343 [ + - ]: 4434 : result = thisMB->get_adjacencies( two_ents, 2, 0, false, all_verts, Interface::UNION );
1344 [ - + ]: 4434 : if( MB_SUCCESS != result ) return result;
1345 : :
1346 [ + - ][ + - ]: 13302 : assert( all_verts.find( entity_to_keep ) != all_verts.end() &&
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ - + ][ # #
# # # # #
# ]
1347 [ + - ]: 8868 : all_verts.find( entity_to_remove ) != all_verts.end() );
1348 : :
1349 : : // . if # vertices != number of corner vertices + 1, continue
1350 [ + - ][ + - ]: 4434 : if( CN::VerticesPerEntity( TYPE_FROM_HANDLE( *rit_rm ) ) + 1 != (int)all_verts.size() ) continue;
[ + - ][ + - ]
[ + + ]
1351 : :
1352 : : // . for the two entities adjacent to kept & removed entity:
1353 [ + - ][ + - ]: 68 : result = create_explicit_adjs( *rit_rm );
1354 [ - + ]: 68 : if( MB_SUCCESS != result ) return result;
1355 [ + - ][ + - ]: 68 : result = create_explicit_adjs( *rit_kp );
1356 [ - + ]: 4434 : if( MB_SUCCESS != result ) return result;
[ + + - ]
1357 : : // . (end for)
1358 : 68 : }
1359 : : // - (end for)
1360 : : }
1361 : :
1362 : 822 : return MB_SUCCESS;
1363 : : }
1364 : :
1365 : 136 : ErrorCode AEntityFactory::create_explicit_adjs( EntityHandle this_ent )
1366 : : {
1367 : : // - get adjacent entities of next higher dimension
1368 [ + - ]: 136 : Range all_adjs;
1369 : : ErrorCode result;
1370 [ + - ]: 136 : result = thisMB->get_adjacencies( &this_ent, 1, thisMB->dimension_from_handle( this_ent ) + 1, false, all_adjs,
1371 [ + - ]: 136 : Interface::UNION );
1372 [ - + ]: 136 : if( MB_SUCCESS != result ) return result;
1373 : :
1374 : : // - create explicit adjacency to these entities
1375 [ + - ][ + - ]: 152 : for( Range::iterator rit = all_adjs.begin(); rit != all_adjs.end(); ++rit )
[ + - ][ + - ]
[ + + ]
1376 : : {
1377 [ + - ][ + - ]: 16 : result = add_adjacency( this_ent, *rit );
1378 [ - + ]: 16 : if( MB_SUCCESS != result ) return result;
1379 : : }
1380 : :
1381 : 136 : return MB_SUCCESS;
1382 : : }
1383 : :
1384 : 2924342 : ErrorCode AEntityFactory::get_adjacency_ptr( EntityHandle entity, std::vector< EntityHandle >*& ptr )
1385 : : {
1386 : 2924342 : ptr = 0;
1387 : :
1388 : : EntitySequence* seq;
1389 [ + - ][ + - ]: 2924342 : ErrorCode rval = thisMB->sequence_manager()->find( entity, seq );
1390 [ + + ][ + - ]: 2924342 : if( MB_SUCCESS != rval || !seq->data()->get_adjacency_data() ) return rval;
[ + - ][ + + ]
[ + + ]
1391 : :
1392 [ + - ][ + - ]: 2899245 : ptr = seq->data()->get_adjacency_data()[entity - seq->data()->start_handle()];
[ + - ][ + - ]
1393 : 2924342 : return MB_SUCCESS;
1394 : : }
1395 : :
1396 : 2642125 : ErrorCode AEntityFactory::get_adjacency_ptr( EntityHandle entity, const std::vector< EntityHandle >*& ptr ) const
1397 : : {
1398 : 2642125 : ptr = 0;
1399 : :
1400 : : EntitySequence* seq;
1401 [ + - ][ + - ]: 2642125 : ErrorCode rval = thisMB->sequence_manager()->find( entity, seq );
1402 [ + - ][ + - ]: 2642125 : if( MB_SUCCESS != rval || !seq->data()->get_adjacency_data() ) return rval;
[ + - ][ + + ]
[ + + ]
1403 : :
1404 [ + - ][ + - ]: 974140 : ptr = seq->data()->get_adjacency_data()[entity - seq->data()->start_handle()];
[ + - ][ + - ]
1405 : 2642125 : return MB_SUCCESS;
1406 : : }
1407 : :
1408 : 356853 : ErrorCode AEntityFactory::set_adjacency_ptr( EntityHandle entity, std::vector< EntityHandle >* ptr )
1409 : : {
1410 : : EntitySequence* seq;
1411 [ + - ][ + - ]: 356853 : ErrorCode rval = thisMB->sequence_manager()->find( entity, seq );
1412 [ - + ]: 356853 : if( MB_SUCCESS != rval ) return rval;
1413 : :
1414 [ + - ][ + - ]: 356853 : if( !seq->data()->get_adjacency_data() && !seq->data()->allocate_adjacency_data() )
[ + + ][ + - ]
[ + - ][ - + ]
[ - + ]
1415 : 0 : return MB_MEMORY_ALLOCATION_FAILED;
1416 : :
1417 [ + - ][ + - ]: 356853 : const EntityHandle index = entity - seq->data()->start_handle();
1418 [ + - ][ + - ]: 356853 : std::vector< EntityHandle >*& ref = seq->data()->get_adjacency_data()[index];
1419 [ + + ]: 356853 : delete ref;
1420 : 356853 : ref = ptr;
1421 : 356853 : return MB_SUCCESS;
1422 : : }
1423 : :
1424 : 4 : void AEntityFactory::get_memory_use( unsigned long long& entity_total, unsigned long long& memory_total )
1425 : : {
1426 : 4 : entity_total = memory_total = 0;
1427 : :
1428 : : // iterate through each element type
1429 : 4 : SequenceData* prev_data = 0;
1430 [ + - ][ + + ]: 48 : for( EntityType t = MBVERTEX; t != MBENTITYSET; t++ )
1431 : : {
1432 [ + - ]: 44 : TypeSequenceManager::iterator i;
1433 [ + - ][ + - ]: 44 : TypeSequenceManager& seqman = thisMB->sequence_manager()->entity_map( t );
1434 [ + - ][ + - ]: 50 : for( i = seqman.begin(); i != seqman.end(); ++i )
[ + - ][ + - ]
[ + + ]
1435 : : {
1436 [ + - ][ + - ]: 6 : if( !( *i )->data()->get_adjacency_data() ) continue;
[ + - ][ + - ]
1437 : :
1438 [ # # ][ # # ]: 0 : if( prev_data != ( *i )->data() )
[ # # ]
1439 : : {
1440 [ # # ][ # # ]: 0 : prev_data = ( *i )->data();
1441 [ # # ]: 0 : memory_total += prev_data->size() * sizeof( AdjacencyVector* );
1442 : : }
1443 : :
1444 : : const AdjacencyVector* vec;
1445 [ # # ][ # # ]: 0 : for( EntityHandle h = ( *i )->start_handle(); h <= ( *i )->end_handle(); ++h )
[ # # ][ # # ]
[ # # ]
1446 : : {
1447 [ # # ]: 0 : get_adjacency_ptr( h, vec );
1448 [ # # ]: 0 : if( vec ) entity_total += vec->capacity() * sizeof( EntityHandle ) + sizeof( AdjacencyVector );
1449 : : }
1450 : : }
1451 : : }
1452 : :
1453 : 4 : memory_total += sizeof( *this ) + entity_total;
1454 : 4 : }
1455 : :
1456 : 4 : ErrorCode AEntityFactory::get_memory_use( const Range& ents_in, unsigned long long& min_per_ent,
1457 : : unsigned long long& amortized )
1458 : : {
1459 : 4 : min_per_ent = amortized = 0;
1460 : 4 : SequenceData* prev_data = 0;
1461 [ + - ][ + - ]: 4 : RangeSeqIntersectIter iter( thisMB->sequence_manager() );
1462 [ + - ][ + - ]: 4 : ErrorCode rval = iter.init( ents_in.begin(), ents_in.end() );
[ + - ]
1463 [ - + ]: 4 : if( MB_SUCCESS != rval ) return rval;
1464 : :
1465 [ + - ][ - + ]: 4 : do
1466 : : {
1467 [ + - ][ + - ]: 4 : AdjacencyVector** array = iter.get_sequence()->data()->get_adjacency_data();
[ + - ]
1468 [ + - ]: 4 : if( !array ) continue;
1469 : :
1470 [ # # ][ # # ]: 0 : EntityID count = iter.get_end_handle() - iter.get_start_handle() + 1;
1471 : : EntityID data_occ = thisMB->sequence_manager()
1472 [ # # ][ # # ]: 0 : ->entity_map( iter.get_sequence()->type() )
[ # # ][ # # ]
1473 [ # # ][ # # ]: 0 : .get_occupied_size( iter.get_sequence()->data() );
[ # # ]
1474 : :
1475 [ # # ][ # # ]: 0 : if( iter.get_sequence()->data() != prev_data )
[ # # ]
1476 : : {
1477 [ # # ][ # # ]: 0 : prev_data = iter.get_sequence()->data();
1478 [ # # ][ # # ]: 0 : amortized += sizeof( AdjacencyVector* ) * iter.get_sequence()->data()->size() * count / data_occ;
[ # # ]
1479 : : }
1480 : :
1481 [ # # ][ # # ]: 0 : array += iter.get_start_handle() - iter.get_sequence()->data()->start_handle();
[ # # ][ # # ]
1482 [ # # ]: 0 : for( EntityID i = 0; i < count; ++i )
1483 : : {
1484 [ # # ]: 0 : if( array[i] ) min_per_ent += sizeof( EntityHandle ) * array[i]->capacity() + sizeof( AdjacencyVector );
1485 : : }
1486 : : } while( MB_SUCCESS == ( rval = iter.step() ) );
1487 : :
1488 : 4 : amortized += min_per_ent;
1489 [ - + ]: 4 : return ( rval == MB_FAILURE ) ? MB_SUCCESS : rval;
1490 : : }
1491 : :
1492 : : /*!
1493 : : calling code is notifying this that an entity is going to be deleted
1494 : : from the database
1495 : : */
1496 : 53857 : ErrorCode AEntityFactory::notify_delete_entity( EntityHandle entity )
1497 : : {
1498 [ + + ]: 53857 : if( TYPE_FROM_HANDLE( entity ) == MBVERTEX )
1499 : : {
1500 [ + - ]: 724 : std::vector< EntityHandle > adj_entities;
1501 [ + + ][ + - ]: 2896 : for( int dim = 1; dim < 4; ++dim )
1502 : : {
1503 [ + - ]: 2172 : ErrorCode rval = get_adjacencies( entity, dim, false, adj_entities );
1504 [ + + ][ - + ]: 2172 : if( rval != MB_SUCCESS && rval != MB_ENTITY_NOT_FOUND ) return rval;
1505 [ - + ]: 2172 : if( !adj_entities.empty() ) return MB_FAILURE;
1506 : 724 : }
1507 : : }
1508 : :
1509 : : // remove any references to this entity from other entities
1510 : 53857 : return remove_all_adjacencies( entity, true );
1511 : : }
1512 : :
1513 [ + - ][ + - ]: 228 : } // namespace moab
|