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 #include <algorithm> 00017 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=false; 00035 } 00036 00037 //---------------------------------------------------------------------------// 00038 // deconstruction function for TFIMapping class 00039 TFIMapping::~TFIMapping() 00040 { 00041 00042 } 00043 00044 //---------------------------------------------------------------------------// 00045 // setup function: 00046 void TFIMapping::setup_this() 00047 { 00048 00049 /* the only things we need to make sure : 00050 1) there are 4 edges, exactly: this is removed 00051 2) the opposite edges have the same meshcount 00052 - if some of the edges are meshed, we need to mesh the opposite edge with 00053 correct meshcount 00054 - if 2 opposite edges are meshed, verify the mesh count 00055 */ 00056 // get iGeom instance from the first ment selection 00057 if (mentSelection.empty()) 00058 return; 00059 00060 //loop over the surfaces 00061 for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++) 00062 { 00063 ModelEnt *me = mit -> first; 00064 int dimME = me->dimension(); 00065 if (dimME != 2) 00066 ECERRCHK(MK_FAILURE, "bad input for TFI Mapping, we can only mesh surfaces"); 00067 //first check whether the surface is meshed or not 00068 if (me->get_meshed_state() >= COMPLETE_MESH) 00069 continue; 00070 int size_index = me->sizing_function_index(); 00071 int mesh_count_surface = -1; 00072 if (size_index >= 0) 00073 mesh_count_surface = me->mk_core()->sizing_function(size_index)->intervals(); 00074 00075 // get the boundary loop of edges 00076 MEntVector boundEdges; 00077 std::vector<int> senses, group_sizes; 00078 me->ModelEnt::boundary(1, boundEdges, &senses, &group_sizes); 00079 //remove this constraint in case of the side-cylinder surface 00080 //if (boundEdges.size() != 4) 00081 // ECERRCHK(MK_FAILURE, "bad input for TFI Mapping, we can only mesh surfaces with 4 edges"); 00082 00083 if (boundEdges.size()<4){ 00084 ModelEnt *oppEdges[2] = {boundEdges[0], boundEdges[1]}; 00085 MEntVector edgesToMesh; 00086 00087 int mesh_count = mesh_count_surface; 00088 bool force = false; 00089 for (int j = 0; j < 2; j++){ 00090 if (oppEdges[j]->get_meshed_state() >= COMPLETE_MESH){ 00091 std::vector<moab::EntityHandle> medges; 00092 oppEdges[j]->get_mesh(1, medges, true); 00093 mesh_count = (int) medges.size(); 00094 force = true; 00095 } 00096 else 00097 { 00098 int indexS = oppEdges[j]->sizing_function_index(); 00099 if (indexS >= 0){ 00100 SizingFunction * sfe = mk_core()->sizing_function(indexS); 00101 if (!force) 00102 { 00103 if (sfe->intervals() > 0) 00104 mesh_count = sfe->intervals(); 00105 else if (sfe->size() > 0) 00106 mesh_count = oppEdges[j]->measure() / sfe->size(); 00107 if (mesh_count % 2 && oppEdges[j]->constrain_even()) 00108 ++mesh_count; 00109 } 00110 } 00111 edgesToMesh.push_back(oppEdges[j]); 00112 } 00113 } 00114 if (edgesToMesh.size() > 0) 00115 { 00116 EdgeMesher * em = (EdgeMesher*) me->mk_core()->construct_meshop("EdgeMesher", edgesToMesh); 00117 if (mesh_count < 0) 00118 { 00119 std::cout << "mesh count not set properly on opposite edges, set it to 10\n"; 00120 mesh_count = 10; // 4 is a nice number, used in the default edge mesher; 00121 // but I like 10 more 00122 } 00123 00124 for (unsigned int j = 0; j < edgesToMesh.size(); j++) 00125 { 00126 int edgeMeshCount = 0; 00127 int edgeSfIndex = 00128 edgesToMesh[j]->sizing_function_index(); 00129 if (edgeSfIndex >= 0) 00130 { 00131 SizingFunction* edgeSf = 00132 mk_core()->sizing_function(edgeSfIndex); 00133 edgeMeshCount = edgeSf->intervals(); 00134 } 00135 if (mesh_count != edgeMeshCount) 00136 { 00137 edgesToMesh[j]->mesh_intervals(mesh_count); 00138 } 00139 if (force) 00140 { 00141 // the opposite edge is already meshed, so the number 00142 // of intervals is a hard constraint for this edge 00143 edgesToMesh[j]->interval_firmness(HARD); 00144 } 00145 edgesToMesh[j]->add_meshop(em); 00146 } 00147 mk_core()->insert_node(em, (GraphNode*)this, 00148 mk_core()->root_node()); 00149 } 00150 } 00151 else{ 00152 00153 // mesh edge 0 and 2 together, and 1 and 3 together (same mesh count) 00154 // look at all settings, to decide proper mesh count 00155 for (int k = 0; k <= 1; k++) 00156 { 00157 // treat first edges 0 and 2, then 1 and 3 00158 ModelEnt * oppEdges[2] = { boundEdges[k], boundEdges[k + 2] }; 00159 MEntVector edgesToMesh;// edges that are not meshed yet 00160 //if one of them is meshed and the other not, use the same mesh count 00161 00162 // take the maximum of the proposed mesh counts, either from sizing function, or mesh intervals 00163 int mesh_count = mesh_count_surface; // could be -1, still 00164 bool force = false; 00165 for (int j = 0; j < 2; j++) 00166 { 00167 if (oppEdges[j]->get_meshed_state() >= COMPLETE_MESH) 00168 { 00169 // in this case, force the other edge to have the same mesh count, do not take it from surface 00170 std::vector<moab::EntityHandle> medges; 00171 oppEdges[j]->get_mesh(1, medges, true); 00172 mesh_count = (int) medges.size(); 00173 force = true; 00174 } 00175 else 00176 { 00177 int indexS = oppEdges[j]->sizing_function_index(); 00178 if (indexS >= 0) 00179 { 00180 SizingFunction * sfe = mk_core()->sizing_function(indexS); 00181 if (!force) 00182 { 00183 // if a sizing function was set on an edge, use 00184 // that rather than a mesh count from the surface 00185 if (sfe->intervals() > 0) 00186 mesh_count = sfe->intervals(); 00187 else if (sfe->size() > 0) 00188 mesh_count = oppEdges[j]->measure() / sfe->size(); 00189 if (mesh_count % 2 && oppEdges[j]->constrain_even()) 00190 ++mesh_count; 00191 } 00192 } 00193 // push it to the list if it is not setup to another mesh op (edge mesher) already 00194 //if (oppEdges[j]->is_meshops_list_empty())// it will create an EdgeMesher later 00195 if ((j == 0 || (oppEdges[j] != oppEdges[0])) && 00196 oppEdges[j]->is_meshops_list_empty()) 00197 { 00198 edgesToMesh.push_back(oppEdges[j]); 00199 } 00200 } 00201 } 00202 // decide on a mesh count now, if edgesToMesh.size()>0 00203 if (edgesToMesh.size() > 0) 00204 { 00205 00206 EdgeMesher * em = (EdgeMesher*) me->mk_core()->construct_meshop("EdgeMesher", edgesToMesh); 00207 if (mesh_count < 0) 00208 { 00209 std::cout << "mesh count not set properly on opposite edges, set it to 10\n"; 00210 mesh_count = 10; // 4 is a nice number, used in the default edge mesher; 00211 // but I like 10 more 00212 } 00213 00214 for (unsigned int j = 0; j < edgesToMesh.size(); j++) 00215 { 00216 int edgeMeshCount = 0; 00217 int edgeSfIndex = 00218 edgesToMesh[j]->sizing_function_index(); 00219 if (edgeSfIndex >= 0) 00220 { 00221 SizingFunction* edgeSf = 00222 mk_core()->sizing_function(edgeSfIndex); 00223 edgeMeshCount = edgeSf->intervals(); 00224 } 00225 if (mesh_count != edgeMeshCount) 00226 { 00227 edgesToMesh[j]->mesh_intervals(mesh_count); 00228 } 00229 if (force) 00230 { 00231 // the opposite edge is already meshed, so the number 00232 // of intervals is a hard constraint for this edge 00233 edgesToMesh[j]->interval_firmness(HARD); 00234 } 00235 edgesToMesh[j]->add_meshop(em); 00236 } 00237 mk_core()->insert_node(em, (GraphNode*)this, 00238 mk_core()->root_node()); 00239 } 00240 } // end loop over pair of opposite edges 00241 } 00242 }// end loop over surfaces 00243 00244 ensure_facet_dependencies(false); 00245 00246 mk_core()->print_graph("AfterTFISetup.eps"); 00247 } 00248 00249 //---------------------------------------------------------------------------// 00250 // execute function: generate the all-quad mesh through the TFI mapping 00251 void TFIMapping::execute_this() 00252 { 00253 00254 //loop over the surfaces 00255 for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++) 00256 { 00257 ModelEnt *me = mit -> first; 00258 //first check whether the surface is meshed or not 00259 if (me->get_meshed_state() >= COMPLETE_MESH){ 00260 00261 #ifdef HAVE_MESQUITE 00262 iBase_EntitySetHandle entityset; 00263 iRel::Error r_err = mk_core()->irel_pair(me->iRelPairIndex())->getEntSetRelation(me->geom_handle(), 0, entityset); 00264 IBERRCHK(r_err, "Trouble get the entityset w.r.t a surface!"); 00265 MeshImprove shapesmooth(mk_core(), false, false, true, false, mk_core()->igeom_instance(me->iGeomIndex())); 00266 shapesmooth.SurfMeshImprove(me->geom_handle(), entityset, iBase_FACE); 00267 #endif 00268 00269 continue; 00270 } 00271 00272 MEntVector boundEdges; 00273 std::vector<int> senses, group_sizes; 00274 me->ModelEnt::boundary(1, boundEdges, &senses, &group_sizes); 00275 set<ModelEnt*> distinctBoundEdges; 00276 distinctBoundEdges.insert(boundEdges.begin(), boundEdges.end()); 00277 if (distinctBoundEdges.size() == 4) 00278 SurfMapping(me); 00279 else 00280 cylinderSurfMapping(me); 00281 00282 //ok, we are done, commit to ME 00283 me->commit_mesh(mit->second, COMPLETE_MESH); 00284 } 00285 00286 } 00287 00288 int TFIMapping::cylinderSurfMapping(ModelEnt *ent) 00289 { 00290 int irelPairIndex = ent->iRelPairIndex(); 00291 00292 // determine whether there is an edge along the linking surface 00293 MEntVector allBoundEdges; 00294 std::vector<int> allSenses, group_sizes; 00295 ent->ModelEnt::boundary(1, allBoundEdges, &allSenses, &group_sizes); 00296 map<ModelEnt*, int> boundEdgeCount; 00297 for (unsigned int i = 0; i < allBoundEdges.size(); ++i) 00298 { 00299 boundEdgeCount[allBoundEdges[i]] = 0; 00300 } 00301 for (unsigned int i = 0; i < allBoundEdges.size(); ++i) 00302 { 00303 ++boundEdgeCount[allBoundEdges[i]]; 00304 } 00305 MEntVector boundEdges; 00306 std::vector<int> boundEdgeSenses; 00307 ModelEnt* linkSurfEdge = NULL; 00308 for (unsigned int i = 0; i < allBoundEdges.size(); ++i) 00309 { 00310 if (boundEdgeCount[allBoundEdges[i]] == 1) 00311 { 00312 boundEdges.push_back(allBoundEdges[i]); 00313 boundEdgeSenses.push_back(allSenses[i]); 00314 } 00315 else 00316 { 00317 linkSurfEdge = allBoundEdges[i]; 00318 } 00319 } 00320 00321 if (boundEdges.size() != 2) 00322 { 00323 ECERRCHK(MK_FAILURE, "Cylinder TFIMapping does not have exactly two distinct bounding edges"); 00324 } 00325 00326 std::cout << "TFIMapping on cylinder\n"; 00327 00328 std::vector<moab::EntityHandle> nList; 00329 std::vector<iBase_EntityHandle> List_i, List_ii; 00330 00331 // get nodes of bounding edge 0 into List_i 00332 boundEdges[0]->get_mesh(0, nList, true); 00333 unsigned int ix = 0; 00334 int size_i = (int)nList.size()-1; 00335 for (ix = 0; ix < nList.size(); ix++) 00336 { 00337 List_i.push_back((iBase_EntityHandle) nList[ix]); 00338 } 00339 // we reverse the first boundary edge if it is "negative" in the loop 00340 if (boundEdgeSenses[0] == -1) 00341 { 00342 std::reverse(List_i.begin(), List_i.end()); 00343 } 00344 nList.clear(); 00345 00346 // get nodes of bounding edge 1 into List_ii 00347 boundEdges[1]->get_mesh(0, nList, true); 00348 int size_ii = nList.size() - 1; 00349 for (ix = 0; ix < nList.size(); ix++) 00350 { 00351 List_ii.push_back((iBase_EntityHandle) nList[ix]); 00352 } 00353 // we reverse the second boundary edge if it is "positive" in the loop 00354 if (boundEdgeSenses[1] == 1) 00355 { 00356 std::reverse(List_ii.begin(), List_ii.end()); 00357 } 00358 00359 if (size_i != size_ii) 00360 ECERRCHK(MK_FAILURE, "Opposite edges have different mesh count, abort"); 00361 00362 // get nodes that are on the linking surface edge, if any, 00363 // and identify where they start on the source and target 00364 int linkingEdgeNodeI = -1; 00365 int linkingEdgeNodeII = -1; 00366 int offset = 0; 00367 std::vector<iBase_EntityHandle> linkEdgeNodeList; 00368 if (linkSurfEdge != NULL) 00369 { 00370 std::vector<moab::EntityHandle> lseNodes; 00371 linkSurfEdge->get_mesh(0, lseNodes, true); 00372 for (ix = 0; ix < lseNodes.size(); ++ix) 00373 { 00374 linkEdgeNodeList.push_back((iBase_EntityHandle)lseNodes[ix]); 00375 } 00376 iBase_EntityHandle nodeOnI = linkEdgeNodeList[0]; 00377 iBase_EntityHandle nodeOnII = linkEdgeNodeList[linkEdgeNodeList.size() - 1]; 00378 for (ix = 0; ix < List_i.size(); ix++) 00379 { 00380 if (nodeOnI == List_i[ix]) 00381 { 00382 linkingEdgeNodeI = (int)ix; 00383 } 00384 else if (nodeOnI == List_ii[ix]) 00385 { 00386 linkingEdgeNodeII = (int)ix; 00387 } 00388 if (nodeOnII == List_i[ix]) 00389 { 00390 linkingEdgeNodeI = (int)ix; 00391 } 00392 else if (nodeOnII == List_ii[ix]) 00393 { 00394 linkingEdgeNodeII = (int)ix; 00395 } 00396 if (linkingEdgeNodeI != -1 && linkingEdgeNodeII != -1) 00397 { 00398 offset = linkingEdgeNodeII - linkingEdgeNodeI; 00399 if (offset < 0) 00400 { 00401 offset += size_i; 00402 } 00403 break; 00404 } 00405 } 00406 if (linkingEdgeNodeI == -1 || linkingEdgeNodeII == -1) 00407 { 00408 ECERRCHK(MK_FAILURE, "Could not find vertices of linking surface edge on source and target."); 00409 } 00410 if (nodeOnI != List_i[linkingEdgeNodeI]) 00411 { 00412 std::reverse(linkEdgeNodeList.begin(), linkEdgeNodeList.end()); 00413 nodeOnI = linkEdgeNodeList[0]; 00414 nodeOnII = linkEdgeNodeList[linkEdgeNodeList.size() - 1]; 00415 } 00416 } 00417 // done with all the initalizations 00418 00419 // get all the position vectors in 3D 00420 std::vector<Vector3D> pos_i(size_i), pos_ii(size_ii); 00421 iGeom::Error g_err = 00422 mk_core()->imesh_instance()->getVtxArrCoords(&(List_i[0]), 00423 size_i, iBase_INTERLEAVED, &(pos_i[0][0])); 00424 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes i"); 00425 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_ii[0]), 00426 size_ii, iBase_INTERLEAVED, &(pos_ii[0][0])); 00427 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes i"); 00428 00429 // compute the number of layers to use based on the sizing function 00430 unsigned int mesh_count = 0; 00431 SizingFunction *surfSizing = 00432 ent->mk_core()->sizing_function(ent->sizing_function_index()); 00433 if (surfSizing->intervals() > 0) 00434 { 00435 mesh_count = surfSizing->intervals(); 00436 if (ent->constrain_even() && mesh_count % 2) 00437 ++mesh_count; 00438 } 00439 else if (surfSizing->size() > 0) 00440 { 00441 double estLinkSurfWidth = 00442 (boundEdges[0]->measure() + boundEdges[1]->measure()) / 2.0; 00443 // the 1 + epsilon factor gets the correct number of edges in a test case 00444 // where the math would work if exact, but fails due to rounding error 00445 double estLinkSurfLength = (1 + 1e-15) * ent->measure() / estLinkSurfWidth; 00446 mesh_count = estLinkSurfLength / surfSizing->size(); 00447 if (!mesh_count) 00448 ++mesh_count; 00449 if (ent->constrain_even() && mesh_count % 2) 00450 ++mesh_count; 00451 } 00452 else if (linkEdgeNodeList.empty()) 00453 { 00454 throw Error(MK_INCOMPLETE_MESH_SPECIFICATION, "Sizing function for cylindrical linking surface with no link edge had neither positive size nor positive intervals."); 00455 } 00456 00457 // compute the interior nodes based on transforming the source and target 00458 // edges in position 00459 unsigned int numCreatedNodes = 0; 00460 if (!linkEdgeNodeList.empty()) 00461 { 00462 if (mesh_count != linkEdgeNodeList.size() - 1) 00463 { 00464 mesh_count = linkEdgeNodeList.size() - 1; 00465 std::cout << "Warning: The number of nodes on the linking surface edge " 00466 << "does not match the number of intervals from the sizing " 00467 << "function on the surface.\n"; 00468 } 00469 numCreatedNodes = (size_i - 1) * (mesh_count - 1); 00470 } 00471 else 00472 { 00473 numCreatedNodes = size_i * (mesh_count - 1); 00474 } 00475 00476 std::vector<iBase_EntityHandle> createdNodes(numCreatedNodes); 00477 std::vector<iBase_EntityHandle> interiorNodes(size_i * (mesh_count-1)); 00478 00479 Vector3D c0, c1; 00480 for (unsigned int k = 1; k < mesh_count; k++) //compute layer by layer 00481 { 00482 double interpolationFactor = 1.0-double(k)/double(mesh_count); 00483 for (int i = 0; i < size_i; i++){ 00484 c0 = pos_i[i]; 00485 c1 = pos_ii[(i + offset) % size_i]; 00486 Vector3D pts = c0*interpolationFactor + c1*(1.0-interpolationFactor); 00487 Vector3D coords; 00488 g_err = ent->igeom_instance()->getEntClosestPtTrimmed(ent->geom_handle(), pts[0], pts[1], pts[2], coords[0], coords[1], coords[2]); 00489 if (g_err) 00490 { 00491 g_err = ent->igeom_instance()->getEntClosestPt(ent->geom_handle(), pts[0], pts[1], pts[2], coords[0], coords[1], coords[2]); 00492 } 00493 IBERRCHK(g_err, "Trouble get the closest xyz coordinates on the linking surface."); 00494 int pastLinkEdgeOffset = 0; 00495 if (i == linkingEdgeNodeI) 00496 { 00497 // this node corresponds to one that should already exist on the edge 00498 interiorNodes[(k - 1)*size_i +i] = linkEdgeNodeList[k]; 00499 } 00500 else if (i > linkingEdgeNodeI && linkingEdgeNodeI >= 0) 00501 { 00502 pastLinkEdgeOffset = -1; 00503 } 00504 iMesh::Error m_err = 00505 mk_core()->imesh_instance()->createVtx(coords[0], coords[1], 00506 coords[2], interiorNodes[(k-1)*size_i+i]); 00507 if (i != linkingEdgeNodeI) 00508 { 00509 createdNodes[(k - 1)*(size_i - 1) + i + pastLinkEdgeOffset] = 00510 interiorNodes[(k - 1)*size_i + i]; 00511 } 00512 IBERRCHK(m_err, "Trouble create the interior node."); 00513 } 00514 } 00515 00516 //finish creating the interior nodes 00517 iBase_EntitySetHandle entityset; 00518 iRel::Error r_err = mk_core()->irel_pair(irelPairIndex)->getEntSetRelation(ent->geom_handle(), 0, entityset); 00519 if (r_err){ 00520 //create the entityset 00521 iMesh::Error m_err = mk_core()->imesh_instance()->createEntSet(true, entityset); 00522 IBERRCHK(m_err, "Trouble create the entity set."); 00523 00524 r_err = mk_core()->irel_pair(irelPairIndex)->setEntSetRelation(ent->geom_handle(), entityset); 00525 IBERRCHK(r_err, "Trouble create the association between the geometry and mesh entity set."); 00526 } 00527 00528 iMesh::Error m_err = mk_core()->imesh_instance()->addEntArrToSet(&createdNodes[0], createdNodes.size(), entityset); 00529 IBERRCHK(m_err, "Trouble add an array of entities to the mesh entity set."); 00530 00531 // copy nodes in a vector to create quads easier 00532 std::vector<iBase_EntityHandle> Nodes((mesh_count+1)*size_i); 00533 //create the int data for mesh nodes on the linking surface 00534 iBase_TagHandle mesh_tag; 00535 // TODO: Don't use a tag here, since multiple TFIMapping may occur at the 00536 // same time 00537 m_err = mk_core()->imesh_instance()->getTagHandle("MeshTFIMapping", mesh_tag); 00538 if (m_err) 00539 { 00540 m_err = mk_core()->imesh_instance()->createTag("MeshTFIMapping", 1, iBase_INTEGER, mesh_tag); 00541 IBERRCHK(m_err, "Trouble create the mesh_tag for the surface."); 00542 } 00543 int intdata = -1; 00544 for (int i = 0; i < size_i; i++){ 00545 intdata++; 00546 m_err = mk_core()->imesh_instance()->setIntData(List_i[i], mesh_tag, intdata); 00547 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00548 00549 Nodes[i] = List_i[i]; 00550 00551 m_err = mk_core()->imesh_instance()->setIntData(List_ii[i], mesh_tag, (intdata + mesh_count*size_i)); 00552 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00553 Nodes[size_i*mesh_count+i] = List_ii[i]; 00554 } 00555 00556 for (int ii = 0; ii < int(interiorNodes.size()); ii++){ 00557 intdata++; 00558 m_err = mk_core()->imesh_instance()->setIntData(interiorNodes[ii], mesh_tag, intdata); 00559 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00560 00561 Nodes[intdata] = interiorNodes[ii]; 00562 } 00563 00564 //we will always create them in the positive orientation, because we already reversed the Lists with nodes 00565 std::vector<iBase_EntityHandle> qNodes(4);//a generic quad 00566 std::vector<iBase_EntityHandle> Quads(size_i*mesh_count); 00567 for (unsigned int k = 0; k < mesh_count; k++){ 00568 for (int i = 0; i < size_i; i++){ 00569 qNodes[0] = Nodes[ k*size_i + i ]; 00570 qNodes[1] = Nodes[ k*size_i + (i + 1)%size_i ]; 00571 qNodes[2] = Nodes[ (k+1)*size_i + (i + 1)%size_i ]; 00572 qNodes[3] = Nodes[ (k+1)*size_i + i ]; 00573 m_err = mk_core()->imesh_instance()->createEnt(iMesh_QUADRILATERAL, &qNodes[0], 4, Quads[k*size_i+i]); 00574 IBERRCHK(m_err, "Trouble create the quadrilateral element."); 00575 } 00576 } 00577 00578 //finish creating the quads 00579 m_err = mk_core()->imesh_instance()->addEntArrToSet(&Quads[0], Quads.size(), entityset); 00580 IBERRCHK(m_err, "Trouble add an array of quads to the mesh entity set."); 00581 //set int data for quads 00582 for (unsigned int i = 0; i < Quads.size(); i++) 00583 { 00584 m_err = mk_core()->imesh_instance()->setIntData(Quads[i], mesh_tag, i); 00585 IBERRCHK(m_err, "Trouble set the int data for quadrilateral elements."); 00586 } 00587 00588 //Get the global id tag 00589 const char *tag = "GLOBAL_ID"; 00590 iBase_TagHandle mesh_id_tag; 00591 m_err = mk_core()->imesh_instance()->getTagHandle(tag, mesh_id_tag); 00592 IBERRCHK(m_err, "Trouble get the mesh_id_tag for 'GLOBAL_ID'."); 00593 00594 std::vector<iBase_EntityHandle> m_Nodes, m_Edges, m_Quads; 00595 00596 //set the int data for Global ID tag 00597 iBase_EntitySetHandle root_set; 00598 int err; 00599 iMesh_getRootSet(mk_core()->imesh_instance()->instance(), &root_set, &err); 00600 assert(!err); 00601 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_VERTEX, iMesh_POINT, m_Nodes); 00602 IBERRCHK(m_err, "Trouble get the node list from the mesh entity set."); 00603 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_EDGE, iMesh_LINE_SEGMENT, m_Edges); 00604 IBERRCHK(m_err, "Trouble get the edges from the mesh entity set."); 00605 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_FACE, iMesh_QUADRILATERAL, m_Quads); 00606 IBERRCHK(m_err, "Trouble get the faces from the mesh entity set."); 00607 00608 for (unsigned int i = 0; i < m_Nodes.size(); i++) 00609 { 00610 m_err = mk_core()->imesh_instance()->setIntData(m_Nodes[i], mesh_id_tag, i); 00611 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00612 } 00613 for (unsigned int i = 0; i < m_Edges.size(); i++) 00614 { 00615 m_err = mk_core()->imesh_instance()->setIntData(m_Edges[i], mesh_id_tag, i); 00616 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00617 } 00618 for (unsigned int i = 0; i < m_Quads.size(); i++) 00619 { 00620 m_err = mk_core()->imesh_instance()->setIntData(m_Quads[i], mesh_id_tag, i); 00621 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00622 } 00623 00624 //SurfImprove(ent->geom_handle(), entityset, iBase_FACE); 00625 mk_core()->save_mesh("InitialMapping.vtk"); 00626 00627 if (_shapeImprove) 00628 { 00629 #ifdef HAVE_MESQUITE 00630 00631 iGeom * ig_inst = mk_core()->igeom_instance(ent->iGeomIndex()); 00632 00633 MeshImprove meshopt(mk_core(), true, false, false, false, ig_inst); 00634 meshopt.SurfMeshImprove(ent->geom_handle(), entityset, iBase_FACE); 00635 00636 #endif 00637 00638 mk_core()->save_mesh("AfterWinslow.vtk"); 00639 #ifdef HAVE_MESQUITE 00640 MeshImprove shapesmooth(mk_core(), false, false, true, false, ig_inst); 00641 shapesmooth.SurfMeshImprove(ent->geom_handle(), entityset, iBase_FACE); 00642 #endif 00643 } 00644 00645 //remove the mesh tag 00646 m_err = mk_core()->imesh_instance()->rmvArrTag(&Quads[0], Quads.size(), mesh_tag); 00647 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00648 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_i[0], List_i.size(), mesh_tag); 00649 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00650 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_ii[0], List_ii.size(), mesh_tag); 00651 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00652 00653 if (interiorNodes.size() > 0) 00654 { 00655 m_err = mk_core()->imesh_instance()->rmvArrTag(&interiorNodes[0], interiorNodes.size(), mesh_tag); 00656 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00657 } 00658 00659 return 1; 00660 } 00661 00662 /***********************************************************************************/ 00663 /*function : SurfMapping */ 00664 /*Date : Mar 3, 2011 */ 00665 /*Description: Generate the mesh on the linking surface by using TFI */ 00666 /* prepare to generate the surface by using TFI mapping interpolation */ 00667 /* 1. Get the mesh(edge mesh) from the bounding geometric edges */ 00668 /* 2. Find the corresponding relationship between edges, vertices */ 00669 /* 3. Check the nodes' corresponding relationship on the 4 bounding edges */ 00670 /* 4. Do the TFI interpolation for interior nodes' location */ 00671 /***********************************************************************************/ 00672 int TFIMapping::SurfMapping(ModelEnt *ent) 00673 { 00674 00675 int irelPairIndex = ent->iRelPairIndex(); 00676 MEntVector boundEdges; 00677 std::vector<int> senses, group_sizes; 00678 ent->ModelEnt::boundary(1, boundEdges, &senses, &group_sizes); 00679 //remove this constraint in case of the side-cylinder case 00680 //if (boundEdges.size() != 4) 00681 // ECERRCHK(MK_FAILURE, "bad input for TFI Mapping, we can only mesh surfaces with 4 edges"); 00682 std::cout << "Surf mapping\n"; 00683 00684 std::vector<iBase_EntityHandle> List_i, List_j, List_ii, List_jj; 00685 00686 std::vector<moab::EntityHandle> nList; 00687 /* 00688 corner[2] NodeList_ii -> corner[3] 00689 ^ ^ 00690 | | 00691 NodeList_j NodeList_jj 00692 ^ ^ 00693 | | 00694 corner[0] NodeList_i -> corner[1] 00695 */ 00696 //get the nodes on each edge 00697 // we want the start of node list i and j to be the same (corner 0) 00698 boundEdges[0]->get_mesh(0, nList, true); // include start and end vertices (corners) 00699 unsigned int ix = 0; 00700 int size_i=(int)nList.size(); 00701 for (ix = 0; ix < nList.size(); ix++) 00702 List_i.push_back((iBase_EntityHandle) nList[ix]); 00703 // if sense is reverse for edge 0, reverse list, 00704 if (senses[0] == -1) 00705 std::reverse(List_i.begin(), List_i.end()); 00706 // so we know for sure corner 0 is at NodeList_i[0]!! 00707 nList.clear(); 00708 boundEdges[1]->get_mesh(0, nList, true); 00709 int size_j=(int)nList.size(); 00710 for (ix = 0; ix < nList.size(); ix++) 00711 List_jj.push_back((iBase_EntityHandle) nList[ix]); 00712 if (senses[1] == -1) 00713 std::reverse(List_jj.begin(), List_jj.end()); 00714 00715 nList.clear(); 00716 boundEdges[2]->get_mesh(0, nList, true); 00717 for (ix = 0; ix < nList.size(); ix++) 00718 List_ii.push_back((iBase_EntityHandle) nList[ix]); 00719 if (senses[2] == 1) // we reverse it if this edge is "positive" in the loop 00720 std::reverse(List_ii.begin(), List_ii.end()); 00721 00722 nList.clear(); 00723 boundEdges[3]->get_mesh(0, nList, true); 00724 for (ix = 0; ix < nList.size(); ix++) 00725 List_j.push_back((iBase_EntityHandle) nList[ix]); 00726 if (senses[3] == 1) // we reverse it if this edge is "positive" in the loop 00727 std::reverse(List_j.begin(), List_j.end()); 00728 00729 if (List_i.size() != List_ii.size()) 00730 ECERRCHK(MK_FAILURE, "opposite edges have different mesh count, abort"); 00731 if (List_j.size() != List_jj.size()) 00732 ECERRCHK(MK_FAILURE, "opposite edges have different mesh count, abort"); 00733 //ok, done with all the initializations 00734 00735 // get all the vectors in 3d 00736 std::vector<Vector3D> pos_ii(List_ii.size()); 00737 std::vector<Vector3D> pos_i(List_i.size()); 00738 std::vector<Vector3D> pos_j(List_j.size()); 00739 std::vector<Vector3D> pos_jj(List_jj.size()); 00740 // iBase_INTERLEAVED 00741 /*getVtxArrCoords( const EntityHandle* vertex_handles, 00742 int vertex_handles_size, 00743 StorageOrder storage_order, 00744 double* coords_out ) const*/ 00745 iGeom::Error g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_ii[0]), List_ii.size(), iBase_INTERLEAVED, &(pos_ii[0][0])); 00746 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes ii."); 00747 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_i[0]), List_i.size(), iBase_INTERLEAVED, &(pos_i[0][0])); 00748 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes i."); 00749 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_j[0]), List_j.size(), iBase_INTERLEAVED, &(pos_j[0][0])); 00750 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes j."); 00751 g_err = mk_core()->imesh_instance()->getVtxArrCoords(&(List_jj[0]), List_jj.size(), iBase_INTERLEAVED, &(pos_jj[0][0])); 00752 IBERRCHK(g_err, "Trouble get the xyz coordinates for nodes jj."); 00753 //calculate the interior nodes based on transforming the top and bottom edges in position 00754 std::vector<iBase_EntityHandle> interiorNodes((List_j.size() - 2) * (List_i.size() - 2)); 00755 // reminder 00756 /* 00757 corner[2] NodeList_ii -> corner[3] 00758 ^ ^ 00759 | | 00760 NodeList_j NodeList_jj 00761 ^ ^ 00762 | | 00763 corner[0] NodeList_i -> corner[1] 00764 */ 00765 Vector3D c0=pos_i[0], c1=pos_i[size_i-1], c2 = pos_ii[0], c3=pos_ii[size_i-1]; 00766 00767 Vector3D bc = 0.5*c0+0.5*c1; 00768 Vector3D tc = 0.5*c2+0.5*c3; 00769 for (int j = 1; j < size_j - 1; j++) // compute layer by layer 00770 // we will start from source (layer 0) to layer j (j>1, j< J-1) 00771 // also , we will look at the target, layer J-1 to layer j 00772 { 00773 00774 // transformation from c0 and c1 to layer j 00775 Matrix3D tr1 , tr2; 00776 //target= A * ( source - 2*sc + tc) + sc 00777 Vector3D cj = 0.5*pos_j[j]+0.5*pos_jj[j]; // center of layer j 00778 computeTransformation(c0, c1, pos_j[j], pos_jj[j], tr1); 00779 // transformation from top, c2 and c3 to layer j 00780 computeTransformation(c2, c3, pos_j[j], pos_jj[j], tr2); 00781 00782 double interpolationFactor = j/(size_j-1.); 00783 00784 for (int i = 1; i < (size_i - 1); i++) 00785 { 00786 // transformation from bottom to layer j; source is b, target is j 00787 Vector3D res1= tr1*(pos_i[i] -2*bc+cj)+bc; 00788 // transformation from top to layer j; source is t, target is j 00789 Vector3D res2= tr2*(pos_ii[i] -2*tc+cj)+tc; 00790 // interpolate this result 00791 Vector3D pts = res1*(1-interpolationFactor) + res2*interpolationFactor; 00792 Vector3D coords; 00793 g_err = ent->igeom_instance()->getEntClosestPtTrimmed(ent->geom_handle(), pts[0], pts[1], pts[2], coords[0], coords[1], 00794 coords[2]); 00795 if (g_err) 00796 { 00797 g_err = ent->igeom_instance()->getEntClosestPt(ent->geom_handle(), pts[0], pts[1], pts[2], coords[0], coords[1], coords[2]); 00798 } 00799 IBERRCHK(g_err, "Trouble get the closest xyz coordinates on the linking surface."); 00800 00801 iMesh::Error m_err = mk_core()->imesh_instance()->createVtx(coords[0], coords[1], coords[2], interiorNodes[(j - 1) 00802 * (size_i - 2) + i - 1]); 00803 IBERRCHK(m_err, "Trouble create the interior node."); 00804 } 00805 } 00806 00807 //finish creating the interior nodes 00808 iBase_EntitySetHandle entityset; 00809 iRel::Error r_err = mk_core()->irel_pair(irelPairIndex)->getEntSetRelation(ent->geom_handle(), 0, entityset); 00810 if (r_err) 00811 { 00812 //create the entityset 00813 iMesh::Error m_err = mk_core()->imesh_instance()->createEntSet(true, entityset); 00814 IBERRCHK(m_err, "Trouble create the entity set."); 00815 00816 r_err = mk_core()->irel_pair(irelPairIndex)->setEntSetRelation(ent->geom_handle(), entityset); 00817 IBERRCHK(r_err, "Trouble create the association between the geometry and mesh entity set."); 00818 } 00819 00820 iMesh::Error m_err = mk_core()->imesh_instance()->addEntArrToSet(&interiorNodes[0], interiorNodes.size(), entityset); 00821 IBERRCHK(m_err, "Trouble add an array of entities to the mesh entity set."); 00822 00823 // copy nodes in a vector to create the quads easier 00824 // they will be arranged in layers, from bottom (j=0) towards top (j=size_j-1) 00825 std::vector<iBase_EntityHandle> Nodes(size_j * size_i); 00826 00827 //create the int data for mesh nodes on the linking surface 00828 iBase_TagHandle mesh_tag; 00829 m_err = mk_core()->imesh_instance()->getTagHandle("MeshTFIMapping", mesh_tag); 00830 if (m_err) 00831 { 00832 m_err = mk_core()->imesh_instance()->createTag("MeshTFIMapping", 1, iBase_INTEGER, mesh_tag); 00833 IBERRCHK(m_err, "Trouble create the mesh_tag for the surface."); 00834 } 00835 int intdata = -1; 00836 for (int i = 0; i < size_i; i++) 00837 { 00838 intdata++; 00839 m_err = mk_core()->imesh_instance()->setIntData(List_i[i], mesh_tag, intdata); 00840 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00841 // bottom row, j=0 00842 Nodes[i]=List_i[i]; 00843 00844 m_err = mk_core()->imesh_instance()->setIntData(List_ii[i], mesh_tag, intdata + size_i); 00845 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00846 // top row, j = size_j-1 00847 Nodes[ (size_i)*(size_j-1)+i] = List_ii[i]; 00848 } 00849 intdata = 2 * size_i - 1; 00850 for (int j = 1; j < size_j - 1; j++) 00851 { 00852 intdata++; 00853 m_err = mk_core()->imesh_instance()->setIntData(List_j[j], mesh_tag, intdata); 00854 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00855 // right column, i=0 00856 Nodes[size_i*j] = List_j[j]; 00857 00858 m_err = mk_core()->imesh_instance()->setIntData(List_jj[j], mesh_tag, intdata + size_j - 2); 00859 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00860 // left column, i = size_i -1 00861 Nodes[size_i*j + size_i-1] = List_jj[j]; 00862 } 00863 00864 intdata = 2 * size_i + 2 * (size_j - 2) - 1; 00865 // it is clear that (size_i-2 > 0 and size_j-2 > 0) iff (interiorNodes.size()>0) 00866 for (unsigned int ii = 0; ii < interiorNodes.size(); ii++) 00867 { 00868 intdata++; 00869 m_err = mk_core()->imesh_instance()->setIntData(interiorNodes[ii], mesh_tag, intdata); 00870 IBERRCHK(m_err, "Trouble set the int data for mesh nodes."); 00871 int j = ii/(size_i-2) + 1; 00872 int i = (ii -(j-1)*(size_i-2)) + 1; 00873 // copy 00874 Nodes[ j*size_i + i] = interiorNodes[ii]; 00875 // compute the row and column 00876 } 00877 00878 // we will always create them in the positive orientation, because we already reversed the Lists 00879 // with nodes 00880 00881 std::vector<iBase_EntityHandle> qNodes(4);// a generic quad 00882 std::vector<iBase_EntityHandle> Quads((size_j - 1) * (size_i - 1)); 00883 for (int j=0; j <size_j-1; j++) 00884 { 00885 for (int i=0; i< size_i-1; i++) 00886 { 00887 qNodes[0] = Nodes[ j *size_i+i ]; 00888 qNodes[1] = Nodes[ j *size_i+i+1]; 00889 qNodes[2] = Nodes[ (j+1)*size_i+i+1]; 00890 qNodes[3] = Nodes[ (j+1)*size_i+i ]; 00891 m_err = mk_core()->imesh_instance()->createEnt(iMesh_QUADRILATERAL, &qNodes[0], 4, Quads[j*(size_i-1)+i]); 00892 IBERRCHK(m_err, "Trouble create the quadrilateral element."); 00893 } 00894 } 00895 00896 //finish creating the quads 00897 m_err = mk_core()->imesh_instance()->addEntArrToSet(&Quads[0], Quads.size(), entityset); 00898 IBERRCHK(m_err, "Trouble add an array of quads to the mesh entity set."); 00899 //set int data for quads 00900 for (unsigned int i = 0; i < Quads.size(); i++) 00901 { 00902 m_err = mk_core()->imesh_instance()->setIntData(Quads[i], mesh_tag, i); 00903 IBERRCHK(m_err, "Trouble set the int data for quadrilateral elements."); 00904 } 00905 00906 //Get the global id tag 00907 const char *tag = "GLOBAL_ID"; 00908 iBase_TagHandle mesh_id_tag; 00909 m_err = mk_core()->imesh_instance()->getTagHandle(tag, mesh_id_tag); 00910 IBERRCHK(m_err, "Trouble get the mesh_id_tag for 'GLOBAL_ID'."); 00911 00912 std::vector<iBase_EntityHandle> m_Nodes, m_Edges, m_Quads; 00913 00914 //set the int data for Global ID tag 00915 iBase_EntitySetHandle root_set; 00916 int err; 00917 iMesh_getRootSet(mk_core()->imesh_instance()->instance(), &root_set, &err); 00918 assert(!err); 00919 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_VERTEX, iMesh_POINT, m_Nodes); 00920 IBERRCHK(m_err, "Trouble get the node list from the mesh entity set."); 00921 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_EDGE, iMesh_LINE_SEGMENT, m_Edges); 00922 IBERRCHK(m_err, "Trouble get the edges from the mesh entity set."); 00923 m_err = mk_core()->imesh_instance()->getEntities(root_set, iBase_FACE, iMesh_QUADRILATERAL, m_Quads); 00924 IBERRCHK(m_err, "Trouble get the faces from the mesh entity set."); 00925 00926 for (unsigned int i = 0; i < m_Nodes.size(); i++) 00927 { 00928 m_err = mk_core()->imesh_instance()->setIntData(m_Nodes[i], mesh_id_tag, i); 00929 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00930 } 00931 for (unsigned int i = 0; i < m_Edges.size(); i++) 00932 { 00933 m_err = mk_core()->imesh_instance()->setIntData(m_Edges[i], mesh_id_tag, i); 00934 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00935 } 00936 for (unsigned int i = 0; i < m_Quads.size(); i++) 00937 { 00938 m_err = mk_core()->imesh_instance()->setIntData(m_Quads[i], mesh_id_tag, i); 00939 IBERRCHK(m_err, "Trouble set the int data for 'GLOBAL_ID'."); 00940 } 00941 00942 //SurfImprove(ent->geom_handle(), entityset, iBase_FACE); 00943 mk_core()->save_mesh("InitialMapping.vtk"); 00944 00945 if (_shapeImprove) 00946 { 00947 #ifdef HAVE_MESQUITE 00948 00949 iGeom * ig_inst = mk_core()->igeom_instance(ent->iGeomIndex()); 00950 00951 MeshImprove meshopt(mk_core(), true, false, false, false, ig_inst); 00952 meshopt.SurfMeshImprove(ent->geom_handle(), entityset, iBase_FACE); 00953 00954 #endif 00955 //mk_core()->save_mesh("AfterLaplace.vtk"); 00956 00957 //if there is the parametric space, let Winslow smooth inside the parametric space 00958 SmoothWinslow(List_i, List_ii, List_j, List_jj, interiorNodes, Quads, mesh_tag, ent); 00959 00960 mk_core()->save_mesh("AfterWinslow.vtk"); 00961 #ifdef HAVE_MESQUITE 00962 MeshImprove shapesmooth(mk_core(), false, false, true, false, ig_inst); 00963 shapesmooth.SurfMeshImprove(ent->geom_handle(), entityset, iBase_FACE); 00964 #endif 00965 } 00966 //remove the mesh tag 00967 m_err = mk_core()->imesh_instance()->rmvArrTag(&Quads[0], Quads.size(), mesh_tag); 00968 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00969 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_i[0], List_i.size(), mesh_tag); 00970 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00971 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_ii[0], List_ii.size(), mesh_tag); 00972 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00973 if (List_j.size() > 2) 00974 { 00975 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_j[0], List_j.size() - 2, mesh_tag); 00976 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00977 m_err = mk_core()->imesh_instance()->rmvArrTag(&List_jj[0], List_jj.size() - 2, mesh_tag); 00978 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00979 } 00980 if (interiorNodes.size() > 0) 00981 { 00982 m_err = mk_core()->imesh_instance()->rmvArrTag(&interiorNodes[0], interiorNodes.size(), mesh_tag); 00983 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 00984 } 00985 00986 return 1; 00987 } 00988 void TFIMapping::computeTransformation(Vector3D & A, Vector3D & B, Vector3D & C, Vector3D & D, 00989 Matrix3D & M) 00990 { 00991 Matrix3D tmpMatrix; 00992 Matrix3D bMatrix; 00993 Vector3D c1=0.5*A+0.5*B; 00994 Vector3D c2=0.5*C+0.5*D; 00995 Vector3D normal=(A-D)*(B-C);// this should be not modified by the transformation 00996 // we add this just to increase the rank of tmpMatrix 00997 // the normal to the "plane" of interest should not be rotated at all 00998 // as if we say that we want A*normal = normal 00999 Vector3D s1=A-2*c1+c2; 01000 Vector3D s2=B-2*c1+c2; 01001 Vector3D t1=C-c1; 01002 Vector3D t2=D-c1; 01003 // so we are looking for M such that 01004 /* 01005 * M*s1 = t1 01006 * M*s2 = t2 01007 * M*n = n 01008 * 01009 * In simple cases, M is identity 01010 */ 01011 01012 tmpMatrix.set_column(0, s1); 01013 tmpMatrix.set_column(1, s2); 01014 tmpMatrix.set_column(2, normal); 01015 bMatrix.set_column(0, t1); 01016 bMatrix.set_column(1, t2); 01017 bMatrix.set_column(2, normal); 01018 01019 double detValue = det(tmpMatrix); 01020 (void) detValue; 01021 assert(detValue*detValue>1.e-20); 01022 01023 //solve the affine mapping matrix, make use of inverse matrix to get affine mapping matrix 01024 Matrix3D InvMatrix = inverse(tmpMatrix); 01025 M = bMatrix*InvMatrix; 01026 01027 } 01028 //smooth the quadrilateral mesh on the linking surface 01029 void TFIMapping::SmoothWinslow(std::vector<iBase_EntityHandle> &List_i, std::vector<iBase_EntityHandle> &List_ii, std::vector< 01030 iBase_EntityHandle> &List_j, std::vector<iBase_EntityHandle> &List_jj, std::vector<iBase_EntityHandle> &interiorNodes, 01031 std::vector<iBase_EntityHandle> &quads, iBase_TagHandle &taghandle, ModelEnt *ent) 01032 { 01033 std::vector<std::set<int> > AdjElements; 01034 std::vector<std::vector<int> > Quads; 01035 std::vector<std::vector<double> > coords; 01036 std::vector<bool> isBnd; 01037 std::vector<iBase_EntityHandle> nodes; 01038 std::vector<double> weight; 01039 01040 bool isParameterized = false; 01041 01042 iGeom::Error g_err = ent->igeom_instance()->isEntParametric(ent->geom_handle(), isParameterized); 01043 IBERRCHK(g_err, "Trouble check whether the surface is parameterized or not."); 01044 isParameterized = false; 01045 01046 //resize the coords to store all the nodes's coordinates on the linking surface 01047 coords.resize(List_i.size() * List_j.size()); 01048 isBnd.resize(coords.size()); 01049 nodes.resize(coords.size()); 01050 for (unsigned int i = 0; i < coords.size(); i++) 01051 coords[i].resize(3); 01052 01053 iMesh::Error m_err; 01054 //input the boundary nodes 01055 for (unsigned int i = 0; i < List_i.size(); i++) 01056 { 01057 m_err = mk_core()->imesh_instance()->getVtxCoord(List_i[i], coords[i][0], coords[i][1], coords[i][2]); 01058 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 01059 nodes[i] = List_i[i]; 01060 isBnd[i] = true; 01061 01062 m_err = mk_core()->imesh_instance()->getVtxCoord(List_ii[i], coords[List_i.size() + i][0], coords[List_i.size() + i][1], 01063 coords[List_i.size() + i][2]); 01064 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 01065 if (isParameterized) 01066 { 01067 double uv[2]; 01068 g_err = ent->igeom_instance()->getEntXYZtoUV(ent->geom_handle(), coords[List_i.size() + i][0], coords[List_i.size() + i][1], 01069 coords[List_i.size() + i][2], uv[0], uv[1]); 01070 IBERRCHK(g_err, "Trouble get the uv from xyz."); 01071 coords[List_i.size() + i][0] = uv[0]; 01072 coords[List_i.size() + i][1] = uv[1]; 01073 } 01074 01075 nodes[List_i.size() + i] = List_ii[i]; 01076 isBnd[List_i.size() + i] = true; 01077 } 01078 if (int(List_j.size()) > 2) 01079 { 01080 for (unsigned int i = 1; i < (List_j.size() - 1); i++) 01081 { 01082 m_err = mk_core()->imesh_instance()->getVtxCoord(List_j[i], coords[2 * List_i.size() + i - 1][0], coords[2 * List_i.size() 01083 + i - 1][1], coords[2 * List_i.size() + i - 1][2]); 01084 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 01085 nodes[2 * List_i.size() + i - 1] = List_j[i]; 01086 isBnd[2 * List_i.size() + i - 1] = true; 01087 01088 m_err = mk_core()->imesh_instance()->getVtxCoord(List_jj[i], coords[2 * List_i.size() + List_j.size() - 2 + i - 1][0], 01089 coords[2 * List_i.size() + List_j.size() - 2 + i - 1][1], coords[2 * List_i.size() + List_j.size() - 2 + i - 1][2]); 01090 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 01091 nodes[2 * List_i.size() + List_j.size() - 2 + i - 1] = List_jj[i]; 01092 isBnd[2 * List_i.size() + List_j.size() - 2 + i - 1] = true; 01093 } 01094 } 01095 //input the interior nodes 01096 if (interiorNodes.size() > 0) 01097 { 01098 for (unsigned int i = 0; i < interiorNodes.size(); i++) 01099 { 01100 m_err = mk_core()->imesh_instance()->getVtxCoord(interiorNodes[i], 01101 coords[2 * List_i.size() + 2 * (List_j.size() - 2) + i][0], coords[2 * List_i.size() + 2 * (List_j.size() - 2) + i][1], 01102 coords[2 * List_i.size() + 2 * (List_j.size() - 2) + i][2]); 01103 IBERRCHK(m_err, "Trouble get the vertex coordinates."); 01104 nodes[2 * List_i.size() + 2 * (List_j.size() - 2) + i] = interiorNodes[i]; 01105 isBnd[2 * List_i.size() + 2 * (List_j.size() - 2) + i] = false; 01106 } 01107 } 01108 01109 //update the AdjElements info 01110 //notice: during this process, adjacent quads will be returned around a node. The quads from source surface and target surface may be returned. 01111 AdjElements.resize(nodes.size()); 01112 for (unsigned int i = 0; i < AdjElements.size(); i++) 01113 { 01114 if (!isBnd[i]) 01115 { 01116 std::vector<iBase_EntityHandle> adjEnts; 01117 adjEnts.clear(); 01118 m_err = mk_core()->imesh_instance()->getEntAdj(nodes[i], iBase_FACE, adjEnts); 01119 IBERRCHK(m_err, "Trouble get the adjacent quads wrt a node."); 01120 for (unsigned int j = 0; j < adjEnts.size(); j++) 01121 { 01122 int index_id = -1; 01123 m_err = mk_core()->imesh_instance()->getIntData(adjEnts[j], taghandle, index_id); 01124 IBERRCHK(m_err, "Trouble get int data for quads."); 01125 AdjElements[i].insert(index_id); 01126 //std::cout<< " i= " << i << " index_id:" << index_id << "\n"; 01127 } 01128 } 01129 } 01130 01131 //update the Quads' info 01132 Quads.resize(quads.size()); 01133 for (unsigned int i = 0; i < Quads.size(); i++) 01134 { 01135 std::vector<iBase_EntityHandle> adjEnts; 01136 adjEnts.clear(); 01137 m_err = mk_core()->imesh_instance()->getEntAdj(quads[i], iBase_VERTEX, adjEnts); 01138 IBERRCHK(m_err, "Trouble get the adjacent nodes wrt a quad."); 01139 01140 assert(adjEnts.size()==4); 01141 Quads[i].resize(4); 01142 01143 for (unsigned int j = 0; j < adjEnts.size(); j++) 01144 { 01145 int index_id = -1; 01146 m_err = mk_core()->imesh_instance()->getIntData(adjEnts[j], taghandle, index_id); 01147 IBERRCHK(m_err, "Trouble get int data for nodes."); 01148 Quads[i][j] = index_id; 01149 } 01150 } 01151 01152 //detect the connectivity 01153 std::vector<std::vector<int> > connect(nodes.size(), std::vector<int>(9)); 01154 for (unsigned int i = 0; i < nodes.size(); i++) 01155 { 01156 if (!isBnd[i]) 01157 { 01158 //there are 4 adjacent quadrilateral elements around node i 01159 //std::cout << " element i:" << i << " AdjElements[i].size() " << AdjElements[i].size() << "\n"; 01160 assert(AdjElements[i].size() == 4); 01161 std::set<int>::iterator it = AdjElements[i].begin(); 01162 int st_index[4]; 01163 //process 4 quad elements 01164 int j = -1; 01165 for (; it != AdjElements[i].end(); it++) 01166 { 01167 j++; 01168 if (int(i) == Quads[*it][0]) 01169 st_index[j] = 0; 01170 else if (int(i) == Quads[*it][1]) 01171 st_index[j] = 1; 01172 else if (int(i) == Quads[*it][2]) 01173 st_index[j] = 2; 01174 else 01175 st_index[j] = 3; 01176 } 01177 it = AdjElements[i].begin(); 01178 connect[i][2] = Quads[*it][(st_index[0] + 3) % 4]; 01179 connect[i][8] = Quads[*it][(st_index[0] + 1) % 4]; 01180 connect[i][1] = Quads[*it][(st_index[0] + 2) % 4]; 01181 //finish processing the quad 1 01182 std::set<int>::iterator it1 = AdjElements[i].begin(); 01183 it1++; 01184 for (j = 1; j < 4; j++, it1++) 01185 { 01186 if (connect[i][8] == Quads[*it1][(st_index[j] + 1) % 4]) 01187 { 01188 connect[i][7] = Quads[*it1][(st_index[j] + 2) % 4]; 01189 connect[i][6] = Quads[*it1][(st_index[j] + 3) % 4]; 01190 break; 01191 } 01192 else if (connect[i][8] == Quads[*it1][(st_index[j] + 3) % 4]) 01193 { 01194 connect[i][7] = Quads[*it1][(st_index[j] + 2) % 4]; 01195 connect[i][6] = Quads[*it1][(st_index[j] + 1) % 4]; 01196 break; 01197 } 01198 else 01199 continue; 01200 } 01201 //finish processing the quad 2 01202 std::set<int>::iterator it2 = AdjElements[i].begin(); 01203 it2++; 01204 for (j = 1; it2 != AdjElements[i].end(); it2++, j++) 01205 { 01206 if (connect[i][2] == Quads[*it2][(st_index[j] + 1) % 4]) 01207 { 01208 connect[i][3] = Quads[*it2][(st_index[j] + 2) % 4]; 01209 connect[i][4] = Quads[*it2][(st_index[j] + 3) % 4]; 01210 break; 01211 } 01212 else if (connect[i][2] == Quads[*it2][(st_index[j] + 3) % 4]) 01213 { 01214 connect[i][3] = Quads[*it2][(st_index[j] + 2) % 4]; 01215 connect[i][4] = Quads[*it2][(st_index[j] + 1) % 4]; 01216 break; 01217 } 01218 else 01219 continue; 01220 } 01221 //finish processing the quad 4; 01222 std::set<int>::iterator it3 = AdjElements[i].begin(); 01223 it3++; 01224 for (j = 1; it3 != AdjElements[i].end(); it3++, j++) 01225 { 01226 if ((it3 != it1) && (it3 != it2)) 01227 { 01228 connect[i][5] = Quads[*it2][(st_index[j] + 2) % 4]; 01229 } 01230 else 01231 continue; 01232 } 01233 } 01234 } 01235 //finish all the initialization 01236 01237 EquipotentialSmooth smoother; 01238 01239 //IsoLaplace smoother; 01240 01241 smoother.SetupData(AdjElements, Quads, coords, isBnd, connect); 01242 smoother.Execute(); 01243 01244 //std::vector<std::vector<double> > coors; 01245 smoother.GetCoords(coords); 01246 01247 //update the new position for nodes 01248 for (unsigned int i = 0; i < nodes.size(); i++) 01249 { 01250 if (!isBnd[i]) 01251 { 01252 double tmp_coord[3] = { coords[i][0], coords[i][1], coords[i][2] }; 01253 if (!isParameterized) 01254 { 01255 iGeom::Error g_err = ent->igeom_instance()->getEntClosestPt(ent->geom_handle(), coords[i][0], coords[i][1], coords[i][2], 01256 tmp_coord[0], tmp_coord[1], tmp_coord[2]); 01257 IBERRCHK(g_err, "Trouble get a closest point on the linking surface."); 01258 } 01259 else 01260 { 01261 iGeom::Error g_err = ent->igeom_instance()->getEntXYZtoUV(ent->geom_handle(), coords[i][0], coords[i][1], tmp_coord[0], 01262 tmp_coord[1], tmp_coord[2]); 01263 IBERRCHK(g_err, "Trouble get the xyz from uv."); 01264 01265 } 01266 m_err = mk_core()->imesh_instance()->setVtxCoord(nodes[i], tmp_coord[0], tmp_coord[1], tmp_coord[2]); 01267 IBERRCHK(m_err, "Trouble set the new coordinates for nodes."); 01268 } 01269 } 01270 01271 //remove the unnecessary tag after smoothing 01272 m_err = mk_core()->imesh_instance()->rmvArrTag(&nodes[0], nodes.size(), taghandle); 01273 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 01274 m_err = mk_core()->imesh_instance()->rmvArrTag(&quads[0], quads.size(), taghandle); 01275 IBERRCHK(m_err, "Trouble remove the tag values from an array of entities."); 01276 //m_err = mk_core()->imesh_instance()->destroyTag(taghandle, 1); 01277 //IBERRCHK(m_err, "Trouble destroy a tag."); 01278 } 01279 01280 } // namespace MeshKit 01281