MeshKit
1.0
|
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