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