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