MeshKit
1.0
|
00001 #include "meshkit/TFIMapping.hpp" 00002 #include "meshkit/MKCore.hpp" 00003 #include "meshkit/EdgeMesher.hpp" 00004 #include "meshkit/ModelEnt.hpp" 00005 #include "meshkit/SizingFunction.hpp" 00006 #include "moab/ReadUtilIface.hpp" 00007 #include "EquipotentialSmooth.hpp" 00008 #ifdef HAVE_MESQUITE 00009 #include "meshkit/MeshImprove.hpp" 00010 #endif 00011 00012 #include <vector> 00013 #include <iostream> 00014 #include <math.h> 00015 #include <map> 00016 00017 const double EPS = 1.0e-6; 00018 00019 namespace MeshKit { 00020 00021 //---------------------------------------------------------------------------// 00022 //Entity Type initialization for TFIMapping meshing 00023 moab::EntityType TFIMapping_tps[] = { moab::MBVERTEX, moab::MBEDGE, moab::MBQUAD, moab::MBMAXTYPE }; 00024 const moab::EntityType* TFIMapping::output_types() 00025 { 00026 return TFIMapping_tps; 00027 } 00028 00029 //---------------------------------------------------------------------------// 00030 // construction function for TFIMapping class 00031 TFIMapping::TFIMapping(MKCore *mk_core, const MEntVector &me_vec) : 00032 MeshScheme(mk_core, me_vec) 00033 { 00034 _shapeImprove=true; 00035 //buildAssociation(); 00036 } 00037 00038 //---------------------------------------------------------------------------// 00039 // deconstruction function for TFIMapping class 00040 TFIMapping::~TFIMapping() 00041 { 00042 00043 } 00044 00045 //---------------------------------------------------------------------------// 00046 // setup function: 00047 void TFIMapping::setup_this() 00048 { 00049 00050 /* the only things we need to make sure : 00051 1) there are 4 edges, exactly 00052 2) the opposite edges have the same meshcount 00053 - if some of the edges are meshed, we need to mesh the opposite edge with 00054 correct meshcount 00055 - if 2 opposite edges are meshed, verify the mesh count 00056 */ 00057 // get iGeom instance from the first ment selection 00058 if (mentSelection.empty()) 00059 return; 00060 00061 //loop over the surfaces 00062 for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++) 00063 { 00064 ModelEnt *me = mit -> first; 00065 int dimME = me->dimension(); 00066 if (dimME != 2) 00067 ECERRCHK(MK_FAILURE, "bad input for TFI Mapping, we can only mesh surfaces"); 00068 //first check whether the surface is meshed or not 00069 if (me->get_meshed_state() >= COMPLETE_MESH) 00070 continue; 00071 int size_index = me->sizing_function_index(); 00072 int mesh_count_surface = -1; 00073 if (size_index >= 0) 00074 mesh_count_surface = me->mk_core()->sizing_function(size_index)->intervals(); 00075 00076 // get the boundary loop of edges 00077 MEntVector boundEdges; 00078 std::vector<int> senses, group_sizes; 00079 me->ModelEnt::boundary(1, boundEdges, &senses, &group_sizes); 00080 if (boundEdges.size() != 4) 00081 ECERRCHK(MK_FAILURE, "bad input for TFI Mapping, we can only mesh surfaces with 4 edges"); 00082 00083 // mesh edge 0 and 2 together, and 1 and 3 together (same mesh count) 00084 // look at all settings, to decide proper mesh count 00085 for (int k = 0; k <= 1; k++) 00086 { 00087 // treat first edges 0 and 2, then 1 and 3 00088 ModelEnt * oppEdges[2] = { boundEdges[k], boundEdges[k + 2] }; 00089 MEntVector edgesToMesh;// edges that are not meshed yet 00090 //if one of them is meshed and the other not, use the same mesh count 00091 00092 // take the maximum of the proposed mesh counts, either from sizing function, or mesh intervals 00093 int mesh_count = mesh_count_surface; // could be -1, still 00094 bool force = false; 00095 for (int j = 0; j < 2; j++) 00096 { 00097 if (oppEdges[j]->get_meshed_state() >= COMPLETE_MESH) 00098 { 00099 // in this case, force the other edge to have the same mesh count, do not take it from surface 00100 std::vector<moab::EntityHandle> medges; 00101 oppEdges[j]->get_mesh(1, medges, true); 00102 mesh_count = (int) medges.size(); 00103 force = true; 00104 } 00105 else 00106 { 00107 int indexS = oppEdges[j]->sizing_function_index(); 00108 if (indexS >= 0) 00109 { 00110 SizingFunction * sfe = mk_core()->sizing_function(indexS); 00111 if (sfe->intervals() > 0 && !force)// if a sizing function was set on an edge, use it, do not 00112 // use the mesh count from surface 00113 // still, a mesh count from opposing edge is very powerful 00114 mesh_count = sfe->intervals(); 00115 } 00116 // push it to the list if it is not setup to another mesh op (edge mesher) already 00117 //if (oppEdges[j]->is_meshops_list_empty())// it will create an EdgeMesher later 00118 edgesToMesh.push_back(oppEdges[j]); 00119 } 00120 } 00121 // decide on a mesh count now, if edgesToMesh.size()>0 00122 if (edgesToMesh.size() > 0) 00123 { 00124 00125 EdgeMesher * em = (EdgeMesher*) me->mk_core()->construct_meshop("EdgeMesher", edgesToMesh); 00126 if (mesh_count < 0) 00127 { 00128 std::cout << "mesh count not set properly on opposite edges, set it to 10\n"; 00129 mesh_count = 10; // 4 is a nice number, used in the default edge mesher; 00130 // but I like 10 more 00131 } 00132 00133 for (unsigned int j = 0; j < edgesToMesh.size(); j++) 00134 { 00135 edgesToMesh[j]->mesh_intervals(mesh_count); 00136 edgesToMesh[j]->interval_firmness(HARD); 00137 edgesToMesh[j]->add_meshop(em); 00138 } 00139 mk_core()->insert_node(em, (MeshOp*) this); 00140 00141 } 00142 } // end loop over pair of opposite edges 00143 }// end loop over surfaces 00144 mk_core()->print_graph("AfterTFISetup.eps"); 00145 } 00146 00147 //---------------------------------------------------------------------------// 00148 // execute function: generate the all-quad mesh through the TFI mapping 00149 void TFIMapping::execute_this() 00150 { 00151 00152 //loop over the surfaces 00153 for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++) 00154 { 00155 ModelEnt *me = mit -> first; 00156 //first check whether the surface is meshed or not 00157 if (me->get_meshed_state() >= COMPLETE_MESH) 00158 continue; 00159 00160 SurfMapping(me); 00161 00162 //ok, we are done, commit to ME 00163 me->commit_mesh(mit->second, COMPLETE_MESH); 00164 } 00165 00166 } 00167 00168 /***********************************************************************************/ 00169 /*function : SurfMapping */ 00170 /*Date : Mar 3, 2011 */ 00171 /*Description: Generate the mesh on the linking surface by using TFI */ 00172 /* prepare to generate the surface by using TFI mapping interpolation */ 00173 /* 1. Get the mesh(edge mesh) from the bounding geometric edges */ 00174 /* 2. Find the corresponding relationship between edges, vertices */ 00175 /* 3. Check the nodes' corresponding relationship on the 4 bounding edges */ 00176 /* 4. Do the TFI interpolation for interior nodes' location */ 00177 /***********************************************************************************/ 00178 int TFIMapping::SurfMapping(ModelEnt *ent) 00179 { 00180 00181 int irelPairIndex = ent->iRelPairIndex(); 00182 MEntVector boundEdges; 00183 std::vector<int> senses, group_sizes; 00184 ent->ModelEnt::boundary(1, boundEdges, &senses, &group_sizes); 00185 if (boundEdges.size() != 4) 00186 ECERRCHK(MK_FAILURE, "bad input for TFI Mapping, we can only mesh surfaces with 4 edges"); 00187 00188 std::vector<iBase_EntityHandle> List_i, List_j, List_ii, List_jj; 00189 00190 std::vector<moab::EntityHandle> nList; 00191 /* 00192 corner[2] NodeList_ii -> corner[3] 00193 ^ ^ 00194 | | 00195 NodeList_j NodeList_jj 00196 ^ ^ 00197 | | 00198 corner[0] NodeList_i -> corner[1] 00199 */ 00200 //get the nodes on each edge 00201 // we want the start of node list i and j to be the same (corner 0) 00202 boundEdges[0]->get_mesh(0, nList, true); // include start and end vertices (corners) 00203 unsigned int ix = 0; 00204 int size_i=(int)nList.size(); 00205 for (ix = 0; ix < nList.size(); ix++) 00206 List_i.push_back((iBase_EntityHandle) nList[ix]); 00207 // if sense is reverse for edge 0, reverse list, 00208 if (senses[0] == -1) 00209 std::reverse(List_i.begin(), List_i.end()); 00210 // so we know for sure corner 0 is at NodeList_i[0]!! 00211 nList.clear(); 00212 boundEdges[1]->get_mesh(0, nList, true); 00213 int size_j=(int)nList.size(); 00214 for (ix = 0; ix < nList.size(); ix++) 00215 List_jj.push_back((iBase_EntityHandle) nList[ix]); 00216 if (senses[1] == -1) 00217 std::reverse(List_jj.begin(), List_jj.end()); 00218 00219 nList.clear(); 00220 boundEdges[2]->get_mesh(0, nList, true); 00221 for (ix = 0; ix < nList.size(); ix++) 00222 List_ii.push_back((iBase_EntityHandle) nList[ix]); 00223 if (senses[2] == 1) // we reverse it if this edge is "positive" in the loop 00224 std::reverse(List_ii.begin(), List_ii.end()); 00225 00226 nList.clear(); 00227 boundEdges[3]->get_mesh(0, nList, true); 00228 for (ix = 0; ix < nList.size(); ix++) 00229 List_j.push_back((iBase_EntityHandle) nList[ix]); 00230 if (senses[3] == 1) // we reverse it if this edge is "positive" in the loop 00231 std::reverse(List_j.begin(), List_j.end()); 00232 00233 if (List_i.size() != List_ii.size()) 00234 ECERRCHK(MK_FAILURE, "opposite edges have different mesh count, abort"); 00235 if (List_j.size() != List_jj.size()) 00236 ECERRCHK(MK_FAILURE, "opposite edges have different mesh count, abort"); 00237 //ok, done with all the initializations 00238 00239 // get all the vectors in 3d 00240 std::vector<Vector3D> pos_ii(List_ii.size()); 00241 std::vector<Vector3D> pos_i(List_i.size()); 00242 std::vector<Vector3D> pos_j(List_j.size()); 00243 std::vector<Vector3D> pos_jj(List_jj.size()); 00244 // iBase_INTERLEAVED 00245 /*getVtxArrCoords( const EntityHandle* vertex_handles, 00246 int vertex_handles_size, 00247 StorageOrder storage_order, 00248 double* coords_out ) const*/ 00249 iGeom::Error g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_ii[0]), List_ii.size(), iBase_INTERLEAVED, &(pos_ii[0][0])); 00250 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes ii."); 00251 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_i[0]), List_i.size(), iBase_INTERLEAVED, &(pos_i[0][0])); 00252 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes ii."); 00253 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_j[0]), List_j.size(), iBase_INTERLEAVED, &(pos_j[0][0])); 00254 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes ii."); 00255 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_jj[0]), List_jj.size(), iBase_INTERLEAVED, &(pos_jj[0][0])); 00256 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes ii."); 00257 //calculate the interior nodes based on transforming the top and bottom edges in position 00258 std::vector<iBase_EntityHandle> InteriorNodes((List_j.size() - 2) * (List_i.size() - 2)); 00259 // reminder 00260 /* 00261 corner[2] NodeList_ii -> corner[3] 00262 ^ ^ 00263 | | 00264 NodeList_j NodeList_jj 00265 ^ ^ 00266 | | 00267 corner[0] NodeList_i -> corner[1] 00268 */ 00269 Vector3D c0=pos_i[0], c1=pos_i[size_i-1], c2 = pos_ii[0], c3=pos_ii[size_i-1]; 00270 00271 Vector3D bc = 0.5*c0+0.5*c1; 00272 Vector3D tc = 0.5*c2+0.5*c3; 00273 for (int j = 1; j < size_j - 1; j++) // compute layer by layer 00274 // we will start from source (layer 0) to layer j (j>1, j< J-1) 00275 // also , we will look at the target, layer J-1 to layer j 00276 { 00277 00278 // transformation from c0 and c1 to layer j 00279 Matrix3D tr1 , tr2; 00280 //target= A * ( source - 2*sc + tc) + sc 00281 Vector3D cj = 0.5*pos_j[j]+0.5*pos_jj[j]; // center of layer j 00282 computeTransformation(c0, c1, pos_j[j], pos_jj[j], tr1); 00283 // transformation from top, c2 and c3 to layer j 00284 computeTransformation(c2, c3, pos_j[j], pos_jj[j], tr2); 00285 00286 double interpolationFactor = j/(size_j-1.); 00287 00288 for (int i = 1; i < (size_i - 1); i++) 00289 { 00290 // transformation from bottom to layer j; source is b, target is j 00291 Vector3D res1= tr1*(pos_i[i] -2*bc+cj)+bc; 00292 // transformation from top to layer j; source is t, target is j 00293 Vector3D res2= tr2*(pos_ii[i] -2*tc+cj)+tc; 00294 // interpolate this result 00295 Vector3D pts = res1*(1-interpolationFactor) + res2*interpolationFactor; 00296 Vector3D coords; 00297 g_err = ent->igeom_instance()->getEntClosestPtTrimmed(ent->geom_handle(), pts[0], pts[1], pts[2], coords[0], coords[1], 00298 coords[2]); 00299 if (g_err) 00300 { 00301 g_err = ent->igeom_instance()->getEntClosestPt(ent->geom_handle(), pts[0], pts[1], pts[2], coords[0], coords[1], coords[2]); 00302 } 00303 IBERRCHK(g_err, "Trouble get the closest xyz coordinates on the linking surface."); 00304 00305 iMesh::Error m_err = mk_core()->imesh_instance()->createVtx(coords[0], coords[1], coords[2], InteriorNodes[(j - 1) 00306 * (size_i - 2) + i - 1]); 00307 IBERRCHK(m_err, "Trouble create the interior node."); 00308 } 00309 } 00310 00311 //finish creating the interior nodes 00312 iBase_EntitySetHandle entityset; 00313 iRel::Error r_err = mk_core()->irel_pair(irelPairIndex)->getEntSetRelation(ent->geom_handle(), 0, entityset); 00314 if (r_err) 00315 { 00316 //create the entityset 00317 iMesh::Error m_err = mk_core()->imesh_instance()->createEntSet(true, entityset); 00318 IBERRCHK(m_err, "Trouble create the entity set."); 00319 00320 r_err = mk_core()->irel_pair(irelPairIndex)->setEntSetRelation(ent->geom_handle(), entityset); 00321 IBERRCHK(r_err, "Trouble create the association between the geometry and mesh entity set."); 00322 } 00323 00324 iMesh::Error m_err = mk_core()->imesh_instance()->addEntArrToSet(&InteriorNodes[0], InteriorNodes.size(), entityset); 00325 IBERRCHK(m_err, "Trouble add an array of entities to the mesh entity set."); 00326 00327 // copy nodes in a vector to create the quads easier 00328 // they will be arranged in layers, from bottom (j=0) towards top (j=size_j-1) 00329 std::vector<iBase_EntityHandle> Nodes(size_j * size_i); 00330 00331 //create the int data for mesh nodes on the linking surface 00332 iBase_TagHandle mesh_tag; 00333 m_err = mk_core()->imesh_instance()->getTagHandle("MeshTFIMapping", mesh_tag); 00334 if (m_err) 00335 { 00336 m_err = mk_core()->imesh_instance()->createTag("MeshTFIMapping", 1, iBase_INTEGER, mesh_tag); 00337 IBERRCHK(m_err, "Trouble create the mesh_tag for the surface."); 00338 } 00339 int intdata = -1; 00340 for (int i = 0; i < size_i; i++) 00341 { 00342 intdata++; 00343 m_err = mk_core()->imesh_instance()->setIntData(List_i[i], mesh_tag, intdata); 00344 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00345 // bottom row, j=0 00346 Nodes[i]=List_i[i]; 00347 00348 m_err = mk_core()->imesh_instance()->setIntData(List_ii[i], mesh_tag, intdata + size_i); 00349 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00350 // top row, j = size_j-1 00351 Nodes[ (size_i)*(size_j-1)+i] = List_ii[i]; 00352 } 00353 intdata = 2 * size_i - 1; 00354 for (int j = 1; j < size_j - 1; j++) 00355 { 00356 intdata++; 00357 m_err = mk_core()->imesh_instance()->setIntData(List_j[j], mesh_tag, intdata); 00358 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00359 // right column, i=0 00360 Nodes[size_i*j] = List_j[j]; 00361 00362 m_err = mk_core()->imesh_instance()->setIntData(List_jj[j], mesh_tag, intdata + size_j - 2); 00363 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00364 // left column, i = size_i -1 00365 Nodes[size_i*j + size_i-1] = List_jj[j]; 00366 } 00367 00368 intdata = 2 * size_i + 2 * (size_j - 2) - 1; 00369 // it is clear that (size_i-2 > 0 and size_j-2 > 0) iff (InteriorNodes.size()>0) 00370 for (unsigned int ii = 0; ii < InteriorNodes.size(); ii++) 00371 { 00372 intdata++; 00373 m_err = mk_core()->imesh_instance()->setIntData(InteriorNodes[ii], mesh_tag, intdata); 00374 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00375 int j = ii/(size_i-2) + 1; 00376 int i = (ii -(j-1)*(size_i-2)) + 1; 00377 // copy 00378 Nodes[ j*size_i + i] = InteriorNodes[ii]; 00379 // compute the row and column 00380 } 00381 00382 // we will always create them in the positive orientation, because we already reversed the Lists 00383 // with nodes 00384 00385 std::vector<iBase_EntityHandle> qNodes(4);// a generic quad 00386 std::vector<iBase_EntityHandle> Quads((size_j - 1) * (size_i - 1)); 00387 for (int j=0; j <size_j-1; j++) 00388 { 00389 for (int i=0; i< size_i-1; i++) 00390 { 00391 qNodes[0] = Nodes[ j *size_i+i ]; 00392 qNodes[1] = Nodes[ j *size_i+i+1]; 00393 qNodes[2] = Nodes[ (j+1)*size_i+i+1]; 00394 qNodes[3] = Nodes[ (j+1)*size_i+i ]; 00395 m_err = mk_core()->imesh_instance()->createEnt(iMesh_QUADRILATERAL, &qNodes[0], 4, Quads[j*(size_i-1)+i]); 00396 IBERRCHK(m_err, "Trouble create the quadrilateral element."); 00397 } 00398 } 00399 00400 //finish creating the quads 00401 m_err = mk_core()->imesh_instance()->addEntArrToSet(&Quads[0], Quads.size(), entityset); 00402 IBERRCHK(m_err, "Trouble add an array of quads to the mesh entity set."); 00403 //set int data for quads 00404 for (unsigned int i = 0; i < Quads.size(); i++) 00405 { 00406 m_err = mk_core()->imesh_instance()->setIntData(Quads[i], mesh_tag, i); 00407 IBERRCHK(m_err, "Trouble set the int data for quadrilateral elements."); 00408 } 00409 00410 //Get the global id tag 00411 const char *tag = "GLOBAL_ID"; 00412 iBase_TagHandle mesh_id_tag; 00413 m_err = mk_core()->imesh_instance()->getTagHandle(tag, mesh_id_tag); 00414 IBERRCHK(m_err, "Trouble get the mesh_id_tag for 'GLOBAL_ID'."); 00415 00416 std::vector<iBase_EntityHandle> m_Nodes, m_Edges, m_Quads; 00417 00418 //set the int data for Global ID tag 00419 iBase_EntitySetHandle root_set; 00420 int err; 00421 iMesh_getRootSet(mk_core()->imesh_instance()->instance(), &root_set, &err); 00422 assert(!err); 00423 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_VERTEX, iMesh_POINT, m_Nodes); 00424 IBERRCHK(m_err, "Trouble get the node list from the mesh entity set."); 00425 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_EDGE, iMesh_LINE_SEGMENT, m_Edges); 00426 IBERRCHK(m_err, "Trouble get the edges from the mesh entity set."); 00427 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_FACE, iMesh_QUADRILATERAL, m_Quads); 00428 IBERRCHK(m_err, "Trouble get the faces from the mesh entity set."); 00429 00430 for (unsigned int i = 0; i < m_Nodes.size(); i++) 00431 { 00432 m_err = mk_core()->imesh_instance()->setIntData(m_Nodes[i], mesh_id_tag, i); 00433 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00434 } 00435 for (unsigned int i = 0; i < m_Edges.size(); i++) 00436 { 00437 m_err = mk_core()->imesh_instance()->setIntData(m_Edges[i], mesh_id_tag, i); 00438 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00439 } 00440 for (unsigned int i = 0; i < m_Quads.size(); i++) 00441 { 00442 m_err = mk_core()->imesh_instance()->setIntData(m_Quads[i], mesh_id_tag, i); 00443 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00444 } 00445 00446 //SurfImprove(ent->geom_handle(), entityset, iBase_FACE); 00447 mk_core()->save_mesh("InitialMapping.vtk"); 00448 00449 if (_shapeImprove) 00450 { 00451 #ifdef HAVE_MESQUITE 00452 00453 iGeom * ig_inst = mk_core()->igeom_instance(ent->iGeomIndex()); 00454 00455 MeshImprove meshopt(mk_core(), true, false, false, false, ig_inst); 00456 meshopt.SurfMeshImprove(ent->geom_handle(), entityset, iBase_FACE); 00457 00458 #endif 00459 //mk_core()->save_mesh("AfterLaplace.vtk"); 00460 00461 //if there is the parametric space, let Winslow smooth inside the parametric space 00462 SmoothWinslow(List_i, List_ii, List_j, List_jj, InteriorNodes, Quads, mesh_tag, ent); 00463 00464 mk_core()->save_mesh("AfterWinslow.vtk"); 00465 #ifdef HAVE_MESQUITE 00466 MeshImprove shapesmooth(mk_core(), false, false, true, false, ig_inst); 00467 shapesmooth.SurfMeshImprove(ent->geom_handle(), entityset, iBase_FACE); 00468 #endif 00469 } 00470 //remove the mesh tag 00471 m_err = mk_core()->imesh_instance()->rmvArrTag(&Quads[0], Quads.size(), mesh_tag); 00472 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00473 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_i[0], List_i.size(), mesh_tag); 00474 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00475 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_ii[0], List_ii.size(), mesh_tag); 00476 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00477 if (List_j.size() > 2) 00478 { 00479 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_j[0], List_j.size() - 2, mesh_tag); 00480 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00481 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_jj[0], List_jj.size() - 2, mesh_tag); 00482 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00483 } 00484 if (InteriorNodes.size() > 0) 00485 { 00486 m_err = mk_core()->imesh_instance()->rmvArrTag(&InteriorNodes[0], InteriorNodes.size(), mesh_tag); 00487 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00488 } 00489 00490 return 1; 00491 } 00492 void TFIMapping::computeTransformation(Vector3D & A, Vector3D & B, Vector3D & C, Vector3D & D, 00493 Matrix3D & M) 00494 { 00495 Matrix3D tmpMatrix; 00496 Matrix3D bMatrix; 00497 Vector3D c1=0.5*A+0.5*B; 00498 Vector3D c2=0.5*C+0.5*D; 00499 Vector3D normal=(A-D)*(B-C);// this should be not modified by the transformation 00500 // we add this just to increase the rank of tmpMatrix 00501 // the normal to the "plane" of interest should not be rotated at all 00502 // as if we say that we want A*normal = normal 00503 Vector3D s1=A-2*c1+c2; 00504 Vector3D s2=B-2*c1+c2; 00505 Vector3D t1=C-c1; 00506 Vector3D t2=D-c1; 00507 // so we are looking for M such that 00508 /* 00509 * M*s1 = t1 00510 * M*s2 = t2 00511 * M*n = n 00512 * 00513 * In simple cases, M is identity 00514 */ 00515 00516 tmpMatrix.set_column(0, s1); 00517 tmpMatrix.set_column(1, s2); 00518 tmpMatrix.set_column(2, normal); 00519 bMatrix.set_column(0, t1); 00520 bMatrix.set_column(1, t2); 00521 bMatrix.set_column(2, normal); 00522 00523 double detValue = det(tmpMatrix); 00524 assert(detValue*detValue>1.e-20); 00525 00526 //solve the affine mapping matrix, make use of inverse matrix to get affine mapping matrix 00527 Matrix3D InvMatrix = inverse(tmpMatrix); 00528 M = bMatrix*InvMatrix; 00529 00530 } 00531 //smooth the quadrilateral mesh on the linking surface 00532 void TFIMapping::SmoothWinslow(std::vector<iBase_EntityHandle> &List_i, std::vector<iBase_EntityHandle> &List_ii, std::vector< 00533 iBase_EntityHandle> &List_j, std::vector<iBase_EntityHandle> &List_jj, std::vector<iBase_EntityHandle> &InteriorNodes, 00534 std::vector<iBase_EntityHandle> &quads, iBase_TagHandle &taghandle, ModelEnt *ent) 00535 { 00536 std::vector<std::set<int> > AdjElements; 00537 std::vector<std::vector<int> > Quads; 00538 std::vector<std::vector<double> > coords; 00539 std::vector<bool> isBnd; 00540 std::vector<iBase_EntityHandle> nodes; 00541 std::vector<double> weight; 00542 00543 bool isParameterized = false; 00544 00545 iGeom::Error g_err = ent->igeom_instance()->isEntParametric(ent->geom_handle(), isParameterized); 00546 IBERRCHK(g_err, "Trouble check whether the surface is parameterized or not."); 00547 isParameterized = false; 00548 00549 //resize the coords to store all the nodes's coordinates on the linking surface 00550 coords.resize(List_i.size() * List_j.size()); 00551 isBnd.resize(coords.size()); 00552 nodes.resize(coords.size()); 00553 for (unsigned int i = 0; i < coords.size(); i++) 00554 coords[i].resize(3); 00555 00556 iMesh::Error m_err; 00557 //input the boundary nodes 00558 for (unsigned int i = 0; i < List_i.size(); i++) 00559 { 00560 m_err = mk_core()->imesh_instance()->getVtxCoord(List_i[i], coords[i][0], coords[i][1], coords[i][2]); 00561 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 00562 nodes[i] = List_i[i]; 00563 isBnd[i] = true; 00564 00565 m_err = mk_core()->imesh_instance()->getVtxCoord(List_ii[i], coords[List_i.size() + i][0], coords[List_i.size() + i][1], 00566 coords[List_i.size() + i][2]); 00567 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 00568 if (isParameterized) 00569 { 00570 double uv[2]; 00571 g_err = ent->igeom_instance()->getEntXYZtoUV(ent->geom_handle(), coords[List_i.size() + i][0], coords[List_i.size() + i][1], 00572 coords[List_i.size() + i][2], uv[0], uv[1]); 00573 IBERRCHK(g_err, "Trouble get the uv from xyz."); 00574 coords[List_i.size() + i][0] = uv[0]; 00575 coords[List_i.size() + i][1] = uv[1]; 00576 } 00577 00578 nodes[List_i.size() + i] = List_ii[i]; 00579 isBnd[List_i.size() + i] = true; 00580 } 00581 if (int(List_j.size()) > 2) 00582 { 00583 for (unsigned int i = 1; i < (List_j.size() - 1); i++) 00584 { 00585 m_err = mk_core()->imesh_instance()->getVtxCoord(List_j[i], coords[2 * List_i.size() + i - 1][0], coords[2 * List_i.size() 00586 + i - 1][1], coords[2 * List_i.size() + i - 1][2]); 00587 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 00588 nodes[2 * List_i.size() + i - 1] = List_j[i]; 00589 isBnd[2 * List_i.size() + i - 1] = true; 00590 00591 m_err = mk_core()->imesh_instance()->getVtxCoord(List_jj[i], coords[2 * List_i.size() + List_j.size() - 2 + i - 1][0], 00592 coords[2 * List_i.size() + List_j.size() - 2 + i - 1][1], coords[2 * List_i.size() + List_j.size() - 2 + i - 1][2]); 00593 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 00594 nodes[2 * List_i.size() + List_j.size() - 2 + i - 1] = List_jj[i]; 00595 isBnd[2 * List_i.size() + List_j.size() - 2 + i - 1] = true; 00596 } 00597 } 00598 //input the interior nodes 00599 if (InteriorNodes.size() > 0) 00600 { 00601 for (unsigned int i = 0; i < InteriorNodes.size(); i++) 00602 { 00603 m_err = mk_core()->imesh_instance()->getVtxCoord(InteriorNodes[i], 00604 coords[2 * List_i.size() + 2 * (List_j.size() - 2) + i][0], coords[2 * List_i.size() + 2 * (List_j.size() - 2) + i][1], 00605 coords[2 * List_i.size() + 2 * (List_j.size() - 2) + i][2]); 00606 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 00607 nodes[2 * List_i.size() + 2 * (List_j.size() - 2) + i] = InteriorNodes[i]; 00608 isBnd[2 * List_i.size() + 2 * (List_j.size() - 2) + i] = false; 00609 } 00610 } 00611 00612 //update the AdjElements info 00613 //notice: during this process, adjacent quads will be returned around a node. The quads from source surface and target surface may be returned. 00614 AdjElements.resize(nodes.size()); 00615 for (unsigned int i = 0; i < AdjElements.size(); i++) 00616 { 00617 if (!isBnd[i]) 00618 { 00619 std::vector<iBase_EntityHandle> adjEnts; 00620 adjEnts.clear(); 00621 m_err = mk_core()->imesh_instance()->getEntAdj(nodes[i], iBase_FACE, adjEnts); 00622 IBERRCHK(m_err, "Trouble get the adjacent quads wrt a node."); 00623 for (unsigned int j = 0; j < adjEnts.size(); j++) 00624 { 00625 int index_id = -1; 00626 m_err = mk_core()->imesh_instance()->getIntData(adjEnts[j], taghandle, index_id); 00627 IBERRCHK(m_err, "Trouble get int data for quads."); 00628 AdjElements[i].insert(index_id); 00629 //std::cout<< " i= " << i << " index_id:" << index_id << "\n"; 00630 } 00631 } 00632 } 00633 00634 //update the Quads' info 00635 Quads.resize(quads.size()); 00636 for (unsigned int i = 0; i < Quads.size(); i++) 00637 { 00638 std::vector<iBase_EntityHandle> adjEnts; 00639 adjEnts.clear(); 00640 m_err = mk_core()->imesh_instance()->getEntAdj(quads[i], iBase_VERTEX, adjEnts); 00641 IBERRCHK(m_err, "Trouble get the adjacent nodes wrt a quad."); 00642 00643 assert(adjEnts.size()==4); 00644 Quads[i].resize(4); 00645 00646 for (unsigned int j = 0; j < adjEnts.size(); j++) 00647 { 00648 int index_id = -1; 00649 m_err = mk_core()->imesh_instance()->getIntData(adjEnts[j], taghandle, index_id); 00650 IBERRCHK(m_err, "Trouble get int data for nodes."); 00651 Quads[i][j] = index_id; 00652 } 00653 } 00654 00655 //detect the connectivity 00656 std::vector<std::vector<int> > connect(nodes.size(), std::vector<int>(9)); 00657 for (unsigned int i = 0; i < nodes.size(); i++) 00658 { 00659 if (!isBnd[i]) 00660 { 00661 //there are 4 adjacent quadrilateral elements around node i 00662 //std::cout << " element i:" << i << " AdjElements[i].size() " << AdjElements[i].size() << "\n"; 00663 assert(AdjElements[i].size() == 4); 00664 std::set<int>::iterator it = AdjElements[i].begin(); 00665 int st_index[4]; 00666 //process 4 quad elements 00667 int j = -1; 00668 for (; it != AdjElements[i].end(); it++) 00669 { 00670 j++; 00671 if (int(i) == Quads[*it][0]) 00672 st_index[j] = 0; 00673 else if (int(i) == Quads[*it][1]) 00674 st_index[j] = 1; 00675 else if (int(i) == Quads[*it][2]) 00676 st_index[j] = 2; 00677 else 00678 st_index[j] = 3; 00679 } 00680 it = AdjElements[i].begin(); 00681 connect[i][2] = Quads[*it][(st_index[0] + 3) % 4]; 00682 connect[i][8] = Quads[*it][(st_index[0] + 1) % 4]; 00683 connect[i][1] = Quads[*it][(st_index[0] + 2) % 4]; 00684 //finish processing the quad 1 00685 std::set<int>::iterator it1 = AdjElements[i].begin(); 00686 it1++; 00687 for (j = 1; j < 4; j++, it1++) 00688 { 00689 if (connect[i][8] == Quads[*it1][(st_index[j] + 1) % 4]) 00690 { 00691 connect[i][7] = Quads[*it1][(st_index[j] + 2) % 4]; 00692 connect[i][6] = Quads[*it1][(st_index[j] + 3) % 4]; 00693 break; 00694 } 00695 else if (connect[i][8] == Quads[*it1][(st_index[j] + 3) % 4]) 00696 { 00697 connect[i][7] = Quads[*it1][(st_index[j] + 2) % 4]; 00698 connect[i][6] = Quads[*it1][(st_index[j] + 1) % 4]; 00699 break; 00700 } 00701 else 00702 continue; 00703 } 00704 //finish processing the quad 2 00705 std::set<int>::iterator it2 = AdjElements[i].begin(); 00706 it2++; 00707 for (j = 1; it2 != AdjElements[i].end(); it2++, j++) 00708 { 00709 if (connect[i][2] == Quads[*it2][(st_index[j] + 1) % 4]) 00710 { 00711 connect[i][3] = Quads[*it2][(st_index[j] + 2) % 4]; 00712 connect[i][4] = Quads[*it2][(st_index[j] + 3) % 4]; 00713 break; 00714 } 00715 else if (connect[i][2] == Quads[*it2][(st_index[j] + 3) % 4]) 00716 { 00717 connect[i][3] = Quads[*it2][(st_index[j] + 2) % 4]; 00718 connect[i][4] = Quads[*it2][(st_index[j] + 1) % 4]; 00719 break; 00720 } 00721 else 00722 continue; 00723 } 00724 //finish processing the quad 4; 00725 std::set<int>::iterator it3 = AdjElements[i].begin(); 00726 it3++; 00727 for (j = 1; it3 != AdjElements[i].end(); it3++, j++) 00728 { 00729 if ((it3 != it1) && (it3 != it2)) 00730 { 00731 connect[i][5] = Quads[*it2][(st_index[j] + 2) % 4]; 00732 } 00733 else 00734 continue; 00735 } 00736 } 00737 } 00738 //finish all the initialization 00739 00740 EquipotentialSmooth smoother; 00741 00742 //IsoLaplace smoother; 00743 00744 smoother.SetupData(AdjElements, Quads, coords, isBnd, connect); 00745 smoother.Execute(); 00746 00747 //std::vector<std::vector<double> > coors; 00748 smoother.GetCoords(coords); 00749 00750 //update the new position for nodes 00751 for (unsigned int i = 0; i < nodes.size(); i++) 00752 { 00753 if (!isBnd[i]) 00754 { 00755 double tmp_coord[3] = { coords[i][0], coords[i][1], coords[i][2] }; 00756 if (!isParameterized) 00757 { 00758 iGeom::Error g_err = ent->igeom_instance()->getEntClosestPt(ent->geom_handle(), coords[i][0], coords[i][1], coords[i][2], 00759 tmp_coord[0], tmp_coord[1], tmp_coord[2]); 00760 IBERRCHK(g_err, "Trouble get a closest point on the linking surface."); 00761 } 00762 else 00763 { 00764 iGeom::Error g_err = ent->igeom_instance()->getEntXYZtoUV(ent->geom_handle(), coords[i][0], coords[i][1], tmp_coord[0], 00765 tmp_coord[1], tmp_coord[2]); 00766 IBERRCHK(g_err, "Trouble get the xyz from uv."); 00767 00768 } 00769 m_err = mk_core()->imesh_instance()->setVtxCoord(nodes[i], tmp_coord[0], tmp_coord[1], tmp_coord[2]); 00770 IBERRCHK(m_err, "Trouble set the new coordinates for nodes."); 00771 } 00772 } 00773 00774 //remove the unnecessary tag after smoothing 00775 m_err = mk_core()->imesh_instance()->rmvArrTag(&nodes[0], nodes.size(), taghandle); 00776 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00777 m_err = mk_core()->imesh_instance()->rmvArrTag(&quads[0], quads.size(), taghandle); 00778 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00779 //m_err = mk_core()->imesh_instance()->destroyTag(taghandle, 1); 00780 //IBERRCHK(m_err, "Trouble destroy a tag."); 00781 } 00782 00783 } // namespace MeshKit 00784