MeshKit  1.0
CopyMesh.cpp
Go to the documentation of this file.
00001 #include "meshkit/CopyMesh.hpp"
00002 #include "meshkit/MKCore.hpp"
00003 #include "meshkit/ModelEnt.hpp"
00004 #include "meshkit/SizingFunction.hpp"
00005 #include "meshkit/RegisterMeshOp.hpp"
00006 #include "meshkit/LocalSet.hpp"
00007 
00008 #include "iMesh_extensions.h"
00009 #include "MBCN.h"
00010 
00011 #define CHKERR(err) do {                        \
00012     if ((err) != iBase_SUCCESS)                   \
00013     return iBase_ErrorType(err);                \
00014     } while(false)
00015 
00016 
00017 namespace MeshKit
00018 {
00019 
00020 // static registration of this  mesh scheme
00021 moab::EntityType CopyMesh_tps[] = { moab::MBVERTEX,
00022                                     moab::MBEDGE,
00023                                     moab::MBTRI,
00024                                     moab::MBHEX,
00025                                     moab::MBMAXTYPE};
00026 const moab::EntityType* CopyMesh::output_types()
00027 { return CopyMesh_tps; }
00028 
00029 CopyMesh::CopyMesh(MKCore *mkcore, const MEntVector &me_vec)
00030     : MeshScheme(mkcore, me_vec),
00031       mesh(mkcore->imesh_instance()),
00032       copyTag(mkcore, "__CopyMeshTag"),
00033       transform(new Copy::Identity()),
00034       copySets(mkcore),
00035       expandSets(mkcore)
00036 {}
00037 
00038 CopyMesh::~CopyMesh()
00039 {
00040     delete transform;
00041 }
00042 
00043 
00044 bool CopyMesh::add_modelent(ModelEnt *model_ent)
00045 {
00046     return MeshOp::add_modelent(model_ent);
00047 }
00048 
00049 void CopyMesh::setup_this()
00050 {
00051     std::cout<< "Setting-up CopyMesh MeshOp" << std::endl;
00052 
00053 }
00054 
00055 void CopyMesh::execute_this()
00056 {
00057     std::cout<< "Executing CopyMesh MeshOp" << std::endl;
00058 
00059     //std::vector<iMesh::EntityHandle> orig_ents(mentSelection.size());
00060 
00061     iBase_EntitySetHandle t = NULL;
00062     for (MEntSelection::iterator mit = mentSelection.begin();
00063          mit != mentSelection.end(); mit++) {
00064         ModelEnt *me = mit->first;
00065         //orig_ents[i++] = reinterpret_cast<iBase_EntityHandle> (me->mesh_handle());
00066         t = reinterpret_cast<iBase_EntitySetHandle> (me->mesh_handle());
00067     }
00068 
00069     LocalSet set(this->mk_core());
00070     std::vector<iBase_EntityHandle> original;
00071     original.clear();
00072     iBase_EntityType type_t;
00073     IBERRCHK(mesh->getEntType((iBase_EntityHandle)t, type_t), *mesh);
00074     // check if this is a set(4)
00075     if((int) type_t !=4){
00076         std::cout << "Invalid model ent set, bailing out.." << std::endl;
00077         exit(0);
00078     }
00079 
00080     IBERRCHK(mesh->getEntities(t, iBase_ALL_TYPES, iMesh_ALL_TOPOLOGIES, original), *mesh);
00081     IBERRCHK(mesh->addEntArrToSet(&original[0], original.size(), set), *mesh);
00082     do_copy(set);
00083 }
00084 
00085 int CopyMesh::getStructure(iMesh_Instance instance,
00086                            iBase_EntitySetHandle set,
00087                            std::vector<iBase_EntityHandle> &ents,
00088                            std::vector<iBase_EntityHandle> &unique_adj,
00089                            std::vector<int> &indices,
00090                            std::vector<int> &offsets)
00091 {
00092     // 1) Get source entities, making sure verts are first
00093     int num;
00094     int err;
00095     iMesh_getNumOfTypeRec(instance, set, iBase_ALL_TYPES, true, &num, &err);
00096     CHKERR(err);
00097 
00098     ents.resize(num);
00099     offsets.resize(num+1);
00100 
00101     iBase_EntityHandle *block = &ents[0];
00102     int block_alloc = ents.size(), block_size, num_verts = 0;
00103     for (int t = iMesh_POINT; t < iMesh_ALL_TOPOLOGIES && block_alloc; ++t) {
00104         iMesh_getEntitiesRec(instance, set, iBase_ALL_TYPES, t, true,
00105                              &block, &block_alloc, &block_size, &err);
00106         CHKERR(err);
00107 
00108         block_alloc -= block_size;
00109         block += block_size;
00110         if (t == iMesh_POINT)
00111             num_verts = block_size;
00112     }
00113 
00114     // 2) Get verts adjacent to all source entitites (verts are adj to themselves)
00115     std::vector<iBase_EntityHandle> all_adj(ents.begin(), ents.begin()+num_verts);
00116 
00117     // first, fill the vertex-vertex adjacencies
00118     for (int i = 0; i < num_verts; ++i)
00119         offsets[i] = i;
00120 
00121     iBase_EntityHandle *tmp_adj = NULL;
00122     int tmp_adj_alloc = 0, tmp_adj_size;
00123     int *tmp_off = &offsets[num_verts];
00124     int tmp_off_alloc = offsets.size() - num_verts, tmp_off_size;
00125     iMesh_getEntArrAdj(instance, &ents[num_verts], ents.size()-num_verts,
00126                        iBase_VERTEX, &tmp_adj, &tmp_adj_alloc, &tmp_adj_size,
00127                        &tmp_off, &tmp_off_alloc, &tmp_off_size, &err);
00128     CHKERR(err);
00129 
00130     // shift all the offsets to account for vertices
00131     for(unsigned int i = num_verts; i < offsets.size(); ++i)
00132         offsets[i] += num_verts;
00133 
00134     all_adj.reserve(all_adj.size() + tmp_adj_size);
00135     all_adj.insert(all_adj.end(), tmp_adj, tmp_adj+tmp_adj_size);
00136     free(tmp_adj);
00137 
00138     // 3) Get unique adjacent vertices and offsets
00139     unique_adj.resize(all_adj.size());
00140     indices.resize(all_adj.size());
00141     std::copy(all_adj.begin(), all_adj.end(), unique_adj.begin());
00142     std::sort(unique_adj.begin(), unique_adj.end());
00143 
00144     size_t unique_size;
00145     unique_size = std::unique(unique_adj.begin(), unique_adj.end()) -
00146             unique_adj.begin();
00147     unique_adj.resize(unique_size);
00148 
00149     for (size_t i = 0; i < all_adj.size(); ++i) {
00150         indices[i] = std::lower_bound(unique_adj.begin(), unique_adj.end(),
00151                                       all_adj[i]) - unique_adj.begin();
00152     }
00153 
00154     return 0;
00155 }
00156 
00157 void CopyMesh::do_copy(iMesh::EntitySetHandle set_handle)
00158 {
00159     assert(transform);
00160 
00161     LocalTag local_tag(this->mk_core());
00162 
00163     std::vector<iBase_EntityHandle> ents;
00164     std::vector<iBase_EntityHandle> verts;
00165     std::vector<int> indices;
00166     std::vector<int> offsets;
00167     //    IBERRCHK(iMesh_getStructure(mesh->instance(), set_handle, ents, verts,
00168     //                                indices, offsets), *mesh);
00169     getStructure(mesh->instance(), set_handle, ents, verts,
00170                  indices, offsets);
00171     // copy the vertices
00172     std::vector<iBase_EntityHandle> new_verts;
00173     transform->transform(mesh, verts, new_verts);
00174     assert(new_verts.size() == verts.size());
00175 
00176     // set the local copy tags on vertices
00177     // XXX: Should this really happen? Doing so adds more entities to copy sets
00178     // than explicitly passed into this function. This may be a domain-specific
00179     // question.
00180     IBERRCHK(mesh->setEHArrData(&verts[0], verts.size(), local_tag,
00181              &new_verts[0]), *mesh);
00182 
00183     // now connect the new vertices to make the higher-dimension entities
00184     connect_the_dots(mesh, local_tag, ents, indices, offsets, new_verts);
00185 
00186     // take care of copy/expand sets
00187     update_sets();
00188 
00189     link_expand_sets(expandSets, local_tag);
00190 
00191     process_ce_sets(mesh, copySets.sets(), local_tag);
00192     process_ce_sets(mesh, expandSets.sets(), local_tag);
00193 
00194     tag_copy_sets(copySets, local_tag, copyTag);
00195 }
00196 
00197 void CopyMesh::update_sets()
00198 {
00199     copySets.update_tagged_sets();
00200     expandSets.update_tagged_sets();
00201 }
00202 
00203 void CopyMesh::tag_copied_sets(const char **tag_names, const char **tag_vals,
00204                                const int num_tags)
00205 {
00206     for (int t = 0; t < num_tags; t++) {
00207         iMesh::TagHandle tag;
00208         IBERRCHK(mesh->getTagHandle(tag_names[t], tag), *mesh);
00209 
00210         tag_copy_sets(mesh, copyTag, copySets.sets(), tag,
00211                       tag_vals ? tag_vals[t] : NULL);
00212     }
00213 }
00214 
00215 void CopyMesh::tag_copied_sets(iMesh::TagHandle *tags, const char **tag_vals,
00216                                const int num_tags)
00217 {
00218     for (int t = 0; t < num_tags; t++)
00219         tag_copy_sets(mesh, copyTag, copySets.sets(), tags[t],
00220                       tag_vals ? tag_vals[t] : NULL);
00221 }
00222 
00223 void connect_the_dots(iMesh *mesh, iBase_TagHandle local_tag,
00224                       const std::vector<iBase_EntityHandle> &ents,
00225                       const std::vector<int> &indices,
00226                       const std::vector<int> &offsets,
00227                       const std::vector<iBase_EntityHandle> &verts)
00228 {
00229     std::vector<iMesh_EntityTopology> topos(ents.size());
00230     IBERRCHK(mesh->getEntArrTopo(&ents[0], ents.size(), &topos[0]), *mesh);
00231 
00232     // scan forward to first non-vertex
00233     size_t pos = 0;
00234     while (pos < topos.size() && iMesh_POINT == topos[pos])
00235         pos++;
00236     if (pos == topos.size()) return;
00237 
00238     // for each run of same size & type
00239     std::vector<iBase_EntityHandle> connect, new_ents;
00240     size_t begin, end = pos;
00241     while (end < ents.size()) {
00242         // get next run; end points to start of *next* element,
00243         // or ents_size if no elems left
00244         begin = end++;
00245 
00246         iMesh_EntityTopology topo = topos[begin];
00247         int vtx_per_ent = offsets[end] - offsets[begin];
00248         while (end < ents.size() &&
00249                topos[end] == topo &&
00250                offsets[end+1] - offsets[end] == vtx_per_ent)
00251             end++;
00252         size_t num_ents = end - begin;
00253 
00254         int mbcn_type;
00255         int num_corner_verts;
00256         iMesh_MBCNType(topo, &mbcn_type);
00257         MBCN_VerticesPerEntity(mbcn_type, &num_corner_verts);
00258 
00259         // build vector of vtx handles
00260         connect.resize(vtx_per_ent * num_ents);
00261         for (size_t i = 0; i < connect.size(); i++)
00262             connect[i] = verts[indices[offsets[begin] + i]];
00263 
00264         // create entities
00265         new_ents.resize(num_ents);
00266 
00267         if (num_corner_verts == vtx_per_ent) {
00268             IBERRCHK(mesh->createEntArr(topo, &connect[0], connect.size(),
00269                      &new_ents[0]), *mesh);
00270         }
00271         else {
00272             // use single-entity function in this case, entity might have higher-
00273             // order nodes (imesh fcn doesn't have argument for # entities)
00274             for (size_t i = 0; i < num_ents; i++) {
00275                 IBERRCHK(mesh->createEnt(topo, &connect[i*vtx_per_ent],
00276                          vtx_per_ent, new_ents[i]), *mesh);
00277             }
00278         }
00279 
00280         // set the local copy tags
00281         IBERRCHK(mesh->setEHArrData(&ents[begin], num_ents, local_tag,
00282                                     &new_ents[0]), *mesh);
00283     }
00284 }
00285 
00286 } // namespace MeshKit
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines