MeshKit  1.0
TFIMapping.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines