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