MeshKit  1.0
MergeMesh.cpp
Go to the documentation of this file.
00001 #include "meshkit/MergeMesh.hpp"
00002 
00003 #include <algorithm>
00004 #include <cstdlib>
00005 #include <cstring>
00006 #include <functional>
00007 #include <string>
00008 #include <vector>
00009 #include <cassert>
00010 #include <iostream>
00011 
00012 #ifdef HAVE_MOAB
00013 #include "MBSkinner.hpp"
00014 #include "MBAdaptiveKDTree.hpp"
00015 #include "MBRange.hpp"
00016 #include "MBCartVect.hpp"
00017 #endif
00018 
00019 namespace MeshKit
00020 {
00021   // static registration of this  mesh scheme
00022   moab::EntityType MergeMesh_tps[] = { moab::MBVERTEX,
00023                                        moab::MBEDGE,
00024                                        moab::MBTRI,
00025                                        moab::MBHEX,
00026                                        moab::MBMAXTYPE};
00027 
00028   const moab::EntityType* MergeMesh::output_types()
00029   { return MergeMesh_tps; }
00030   
00031   MergeMesh::MergeMesh(MKCore *mkcore, const MEntVector &me_vec)
00032     : MeshScheme(mkcore, me_vec),
00033       imeshImpl(mkcore->imesh_instance()), mbImpl (mkcore->moab_instance())
00034   {
00035     mergeTol = 1e-4;
00036     updateSets = 0;
00037     doMerge = 1;
00038     mergeTag = NULL;
00039   }
00040 
00041   MergeMesh::~MergeMesh()
00042   {
00043 #ifdef HAVE_MOAB
00044     if (mbMergeTag) mbImpl->tag_delete(mbMergeTag);
00045 #endif
00046   }
00047 
00048   bool MergeMesh::add_modelent(ModelEnt *model_ent)
00049   {
00050     return MeshOp::add_modelent(model_ent);
00051   }
00052 
00053   void MergeMesh::set_merge_params(double merge_tol, int updatesets,
00054                                    int domerge, iBase_TagHandle merge_tag)
00055   {
00056     mergeTol = merge_tol;
00057     updateSets = updatesets;
00058     doMerge = domerge;
00059     mergeTag = merge_tag;
00060   }
00061 
00062   void MergeMesh::setup_this()
00063   {
00064     std::cout << "IN SETUPTHIS MERGEMESH " << std::endl;
00065 
00066   }
00067 
00068   void MergeMesh::execute_this()
00069   {
00070     std::cout << "IN EXTHIS MERGEMESH " << std::endl;
00071 
00072     std::vector<iBase_EntityHandle> ents(mentSelection.size());
00073     int dim;
00074     for (MEntSelection::iterator mit = mentSelection.begin();
00075          mit != mentSelection.end(); mit++) {
00076       ModelEnt *me = mit->first;
00077       dim  = me->dimension();
00078     }
00079 
00080     if(dim == 3){
00081       imeshImpl->getEntities(0, iBase_REGION, iMesh_ALL_TOPOLOGIES,
00082                              ents);
00083     }
00084     else if (dim == 2){
00085       imeshImpl->getEntities(0, iBase_FACE, iMesh_ALL_TOPOLOGIES,
00086                              ents);
00087     }
00088     merge_entities(&ents[0], ents.size(), mergeTol, doMerge, updateSets,
00089                    mergeTag);
00090   }
00091 
00092   void MergeMesh::merge_entities(iBase_EntityHandle *elems,
00093                                  int elems_size,
00094                                  const double merge_tol,
00095                                  const int do_merge,
00096                                  const int update_sets,
00097                                  iBase_TagHandle merge_tag)  
00098   {
00099     mergeTol = merge_tol;
00100     mergeTolSq = merge_tol*merge_tol;
00101   
00102 #ifdef HAVE_MOAB  
00103     MBRange tmp_elems;
00104     tmp_elems.insert((MBEntityHandle*)elems, (MBEntityHandle*)elems + elems_size);
00105     MBErrorCode result = merge_entities(tmp_elems, do_merge, update_sets,
00106                                         (MBTag)merge_tag);
00107     if (result != MB_SUCCESS)
00108       throw MKException(iBase_FAILURE, "");
00109 #else
00110     throw MKException(iBase_NOT_SUPPORTED, "");
00111 #endif
00112   }
00113 
00114   void MergeMesh::perform_merge(iBase_TagHandle merge_tag) 
00115   {
00116 #ifdef HAVE_MOAB
00117     // put into a range
00118     MBErrorCode result = perform_merge((MBTag) merge_tag);
00119     if (result != MB_SUCCESS)
00120       throw MKException(iBase_FAILURE, "");
00121 #else
00122     throw MKException(iBase_NOT_SUPPORTED, "");
00123 #endif
00124   }
00125 
00126 #ifdef HAVE_MOAB
00127   MBErrorCode MergeMesh::merge_entities(MBRange &elems,
00128                                         const int do_merge,
00129                                         const int update_sets,
00130                                         MBTag merge_tag) 
00131   {
00132     // get the skin of the entities
00133     MBSkinner skinner(mbImpl);
00134     MBRange skin_range;
00135     MBErrorCode result = skinner.find_skin(0, elems, 0, skin_range);
00136     if (MB_SUCCESS != result) return result;
00137 
00138     // create a tag to mark merged-to entity; reuse tree_root
00139     MBEntityHandle tree_root = 0;
00140     if (0 == merge_tag) {
00141       //result = mbImpl->tag_create("__merge_tag", sizeof(MBEntityHandle), 
00142       //                            MB_TAG_DENSE, MB_TYPE_HANDLE,
00143       //                            mbMergeTag, &tree_root);
00144       result = mbImpl->tag_get_handle("__merge_tag", 1, MB_TYPE_HANDLE,
00145                                       mbMergeTag, MB_TAG_DENSE|MB_TAG_CREAT,
00146                                       &tree_root);
00147       if (MB_SUCCESS != result) return result;
00148     }
00149     else mbMergeTag = merge_tag;
00150   
00151     // build a kd tree with the vertices
00152     MBAdaptiveKDTree kd(mbImpl);
00153     result = kd.build_tree(skin_range, &tree_root);
00154     if (MB_SUCCESS != result) return result;
00155 
00156     // find matching vertices, mark them
00157     result = find_merged_to(kd, tree_root, mbMergeTag);
00158     if (MB_SUCCESS != result) return result;
00159   
00160     // merge them if requested
00161     if (do_merge) {
00162       result = perform_merge(mbMergeTag);
00163       if (MB_SUCCESS != result) return result;
00164     }
00165   
00166     return MB_SUCCESS;
00167   }
00168 
00169   MBErrorCode MergeMesh::perform_merge(MBTag merge_tag) 
00170   {
00171     if (deadEnts.size()==0){
00172       std::cout << "\nWarning: Geometries don't have a common face; Nothing to merge" << std::endl;
00173       return MB_SUCCESS; //nothing to merge carry on with the program
00174     }
00175     if (mbImpl->type_from_handle(*deadEnts.rbegin()) != MBVERTEX) 
00176       return MB_FAILURE;
00177   
00178     std::vector<MBEntityHandle> merge_tag_val(deadEnts.size());
00179     MBErrorCode result = mbImpl->tag_get_data(merge_tag, deadEnts, &merge_tag_val[0]);
00180     if (MB_SUCCESS != result) return result;
00181   
00182     MBRange::iterator rit;
00183     unsigned int i;
00184     for (rit = deadEnts.begin(), i = 0; rit != deadEnts.end(); rit++, i++) {
00185       assert(merge_tag_val[i]);
00186       result = mbImpl->merge_entities(merge_tag_val[i], *rit, false, false);
00187       if (MB_SUCCESS != result) return result;
00188     }
00189   
00190     return mbImpl->delete_entities(deadEnts);
00191   }
00192 
00193   MBErrorCode MergeMesh::find_merged_to(MBAdaptiveKDTree & tree, MBEntityHandle &tree_root, MBTag merge_tag)
00194   {
00195     MBAdaptiveKDTreeIter iter;
00196     //MBAdaptiveKDTree tree(mbImpl);
00197   
00198     // evaluate vertices in this leaf
00199     MBRange leaf_range, leaf_range2;
00200     std::vector<MBEntityHandle> sorted_leaves;
00201     std::vector<double> coords;
00202     std::vector<MBEntityHandle> merge_tag_val, leaves_out;
00203   
00204     MBErrorCode result = tree.get_tree_iterator(tree_root, iter);
00205     if (MB_SUCCESS != result) return result;
00206     while (result == MB_SUCCESS) {
00207       sorted_leaves.push_back( iter.handle() );
00208       result = iter.step();
00209     }
00210     if (result != MB_ENTITY_NOT_FOUND)
00211       return result;
00212     std::sort( sorted_leaves.begin(), sorted_leaves.end() );
00213   
00214     std::vector<MBEntityHandle>::iterator it;
00215     for (it = sorted_leaves.begin(); it != sorted_leaves.end(); ++it) {
00216 
00217       leaf_range.clear();
00218       result = mbImpl->get_entities_by_handle(*it, leaf_range);
00219       if (MB_SUCCESS != result) return result;
00220       coords.resize(3*leaf_range.size());
00221       merge_tag_val.resize(leaf_range.size());
00222       result = mbImpl->get_coords(leaf_range, &coords[0]);
00223       if (MB_SUCCESS != result) return result;
00224       result = mbImpl->tag_get_data(merge_tag, leaf_range, &merge_tag_val[0]);
00225       if (MB_SUCCESS != result) return result;
00226       MBRange::iterator rit;
00227       unsigned int i;
00228       bool inleaf_merged, outleaf_merged = false;
00229       unsigned int lr_size = leaf_range.size();
00230     
00231       for (i = 0, rit = leaf_range.begin(); i != lr_size; rit++, i++) {
00232         if (0 != merge_tag_val[i]) continue;
00233         MBCartVect from(&coords[3*i]);
00234         inleaf_merged = false;
00235 
00236         // check close-by leaves too
00237         leaves_out.clear();
00238         result = tree.distance_search( from.array(), mergeTol,
00239                                              leaves_out);
00240         leaf_range2.clear();
00241         for (std::vector<MBEntityHandle>::iterator vit = leaves_out.begin();
00242              vit != leaves_out.end(); vit++) {
00243           if (*vit > *it) { // if we haven't visited this leaf yet in the outer loop
00244             result = mbImpl->get_entities_by_handle(*vit, leaf_range2, MBInterface::UNION);
00245             if (MB_SUCCESS != result) return result;
00246           }
00247         }
00248         if (!leaf_range2.empty()) {
00249           coords.resize(3*(lr_size+leaf_range2.size()));
00250           merge_tag_val.resize(lr_size+leaf_range2.size());
00251           result = mbImpl->get_coords(leaf_range2, &coords[3*lr_size]);
00252           if (MB_SUCCESS != result) return result;
00253           result = mbImpl->tag_get_data(merge_tag, leaf_range2, &merge_tag_val[lr_size]);
00254           if (MB_SUCCESS != result) return result;
00255           outleaf_merged = false;
00256         }
00257 
00258         // check other verts in this leaf
00259         for (unsigned int j = i+1; j < merge_tag_val.size(); j++) {
00260           MBEntityHandle to_ent = j >= lr_size ? leaf_range2[j-lr_size] : 
00261             leaf_range[j];
00262         
00263           if (*rit == to_ent) continue;
00264         
00265           if ((from - MBCartVect(&coords[3*j])).length_squared() < mergeTolSq) {
00266             merge_tag_val[j] = *rit;
00267             if (j < lr_size){
00268               inleaf_merged = true;}
00269             else{
00270               outleaf_merged = true;}
00271 
00272             deadEnts.insert(to_ent);
00273           }
00274 
00275         }
00276         if (outleaf_merged) {
00277           result = mbImpl->tag_set_data(merge_tag, leaf_range2, &merge_tag_val[leaf_range.size()]);
00278           if (MB_SUCCESS != result) return result;
00279           outleaf_merged = false;
00280         }
00281         if (inleaf_merged) {
00282           result = mbImpl->tag_set_data(merge_tag, leaf_range, &merge_tag_val[0]);
00283           if (MB_SUCCESS != result) return result;
00284         }
00285 
00286       }
00287     }
00288     return MB_SUCCESS;
00289   }
00290 
00291 #endif // ifdef MOAB
00292 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines