LCOV - code coverage report
Current view: top level - algs/Sweep - OneToOneSwept.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 500 562 89.0 %
Date: 2020-07-01 15:24:36 Functions: 17 18 94.4 %
Branches: 801 1872 42.8 %

           Branch data     Line data    Source code
       1                 :            : #ifdef _WIN32
       2                 :            : #define _USE_MATH_DEFINES
       3                 :            : #endif
       4                 :            : 
       5                 :            : #include "meshkit/OneToOneSwept.hpp"
       6                 :            : #include "meshkit/iMesh.hpp"
       7                 :            : #include "meshkit/EdgeMesher.hpp"
       8                 :            : #include "meshkit/TFIMapping.hpp"
       9                 :            : #ifdef HAVE_MESQUITE
      10                 :            : #include "meshkit/MeshImprove.hpp"
      11                 :            : #endif
      12                 :            : #include <iostream>
      13                 :            : #include <algorithm>
      14                 :            : #include <math.h>
      15                 :            : #include <map>
      16                 :            : #ifdef HAVE_ARMADILLO
      17                 :            : #include "SurfProHarmonicMap.hpp"
      18                 :            : #endif
      19                 :            : 
      20                 :            : namespace MeshKit {
      21                 :            : 
      22                 :            : //---------------------------------------------------------------------------//
      23                 :            : //Entity Type initialization for OneToOneSwept meshing
      24                 :            : moab::EntityType OneToOneSwept_tps[] = { moab::MBVERTEX, moab::MBQUAD, moab::MBHEX, moab::MBMAXTYPE };
      25                 :         40 : const moab::EntityType* OneToOneSwept::output_types()
      26                 :            : {
      27                 :         40 :   return OneToOneSwept_tps;
      28                 :            : }
      29                 :            : 
      30                 :            : //---------------------------------------------------------------------------//
      31                 :            : // construction function for OneToOneSwept class
      32                 :          6 : OneToOneSwept::OneToOneSwept(MKCore *mk_core, const MEntVector &me_vec) :
      33 [ +  - ][ +  - ]:          6 :   MeshScheme(mk_core, me_vec)
         [ +  - ][ +  - ]
      34                 :            : {
      35                 :          6 : }
      36                 :            : 
      37                 :            : //---------------------------------------------------------------------------//
      38                 :            : // deconstruction function for OneToOneSwept class
      39                 :         18 : OneToOneSwept::~OneToOneSwept()
      40                 :            : {
      41         [ -  + ]:         12 : }
      42                 :            : 
      43                 :            : // these have to be called before setup, otherwise we don't know source and target
      44                 :            : //---------------------------------------------------------------------------//
      45                 :            : // set the source surface function
      46                 :          6 : void OneToOneSwept::SetSourceSurface(int index)
      47                 :            : {
      48                 :          6 :   index_src = index;
      49                 :          6 : }
      50                 :            : 
      51                 :            : //---------------------------------------------------------------------------//
      52                 :            : // set the target surface function
      53                 :          6 : void OneToOneSwept::SetTargetSurface(int index)
      54                 :            : {
      55                 :          6 :   index_tar = index;
      56                 :          6 : }
      57                 :            : 
      58                 :            : //---------------------------------------------------------------------------//
      59                 :            : // setup function: define the size between the different layers
      60                 :          6 : void OneToOneSwept::setup_this()
      61                 :            : {
      62                 :            :   //compute the number of intervals for the associated ModelEnts, from the size set on them
      63                 :            :   //the sizing function they point to, or a default sizing function
      64                 :            : 
      65         [ -  + ]:          6 :   if (mentSelection.empty())
      66                 :          6 :     return;
      67         [ +  - ]:          6 :   ModelEnt * firstME = (mentSelection.begin())->first;
      68                 :          6 :   igeom_inst = firstME->igeom_instance();
      69                 :            :   /*moab::Interface **/
      70                 :          6 :   mb = mk_core()->moab_instance();// we should get it also from
      71                 :            :   // model entity, if we have multiple moab instances running around
      72                 :            : 
      73                 :          6 :   const char *tag = "GLOBAL_ID";
      74                 :          6 :   iGeom::Error g_err = igeom_inst->getTagHandle(tag, geom_id_tag);
      75                 :          6 :   IBERRCHK(g_err, "Trouble get the geom_id_tag for 'GLOBAL_ID'.");
      76                 :            : 
      77 [ +  - ][ +  - ]:         12 :   for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
                 [ +  + ]
      78                 :            :   {
      79         [ +  - ]:          6 :     ModelEnt *me = mit->first;
      80                 :            :     //first check to see whether entity is meshed
      81 [ +  - ][ +  - ]:          6 :     if (me->get_meshed_state() >= COMPLETE_MESH || me->mesh_intervals() > 0)
         [ +  - ][ -  + ]
                 [ -  + ]
      82                 :          0 :       continue;
      83                 :            : 
      84 [ +  - ][ +  - ]:          6 :     SizingFunction *sf = mk_core()->sizing_function(me->sizing_function_index());
                 [ +  - ]
      85 [ -  + ][ #  # ]:          6 :     if (!sf && me -> mesh_intervals() < 0 && me -> interval_firmness() == DEFAULT && mk_core()->sizing_function(0))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ -  + ]
      86 [ #  # ][ #  # ]:          0 :       sf = mk_core()->sizing_function(0);
      87                 :            : 
      88 [ -  + ][ #  # ]:          6 :     if (!sf && me -> mesh_intervals() < 0 && me -> interval_firmness() == DEFAULT)
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
      89                 :            :     {
      90                 :            :       //no sizing set, just assume default #intervals as 4
      91         [ #  # ]:          0 :       me->mesh_intervals(4);
      92         [ #  # ]:          0 :       me->interval_firmness(DEFAULT);
      93                 :            :     }
      94                 :            :     else
      95                 :            :     {
      96                 :            :       //check # intervals first, then size, and just choose for now
      97 [ +  - ][ +  + ]:          6 :       if (sf->intervals() > 0)
      98                 :            :       {
      99 [ +  - ][ -  + ]:          2 :         if (me->constrain_even() && sf->intervals() % 2)
         [ #  # ][ #  # ]
                 [ -  + ]
     100 [ #  # ][ #  # ]:          0 :           me -> mesh_intervals(sf->intervals() + 1);
     101                 :            :         else
     102 [ +  - ][ +  - ]:          2 :           me -> mesh_intervals(sf->intervals());
     103         [ +  - ]:          2 :         me -> interval_firmness(HARD);
     104                 :            :       }
     105 [ +  - ][ +  - ]:          4 :       else if (sf->size() > 0)
     106                 :            :       {
     107                 :            :         // FIXME: This calculation is bogus if size means edge lengths.
     108                 :            :         // This should divide by the measurement of the source surface.
     109 [ +  - ][ +  - ]:          4 :         int intervals = me->measure() / sf->size();
     110         [ -  + ]:          4 :         if (!intervals)
     111                 :          0 :           intervals++;
     112 [ +  - ][ -  + ]:          4 :         if (me->constrain_even() && intervals % 2)
         [ #  # ][ -  + ]
     113                 :          0 :           intervals++;
     114         [ +  - ]:          4 :         me->mesh_intervals(intervals);
     115         [ +  - ]:          4 :         me->interval_firmness(SOFT);
     116                 :            :       }
     117                 :            :       else
     118         [ #  # ]:          0 :         throw Error(MK_INCOMPLETE_MESH_SPECIFICATION, "Sizing function for edge had neither positive size nor positive intervals.");
     119                 :            :     }
     120                 :            : 
     121         [ +  - ]:          6 :     int numIntervals = me->mesh_intervals();
     122 [ +  - ][ +  - ]:          6 :     if (!sf || sf->intervals() != numIntervals)
         [ +  + ][ +  + ]
     123                 :            :     {
     124 [ +  - ][ +  - ]:          4 :       sf = new SizingFunction(mk_core(), numIntervals, -1.);
                 [ +  - ]
     125                 :            :     }
     126                 :            : 
     127         [ +  - ]:          6 :     std::vector<iBase_EntityHandle> gFaces;
     128 [ +  - ][ +  - ]:          6 :     g_err = igeom_inst->getEntAdj(me->geom_handle(), iBase_FACE, gFaces);
     129         [ +  - ]:          6 :     IBERRCHK(g_err, "Trouble get the geometrical adjacent to the solid");
     130                 :            :     //select the source surface and target surface
     131                 :            :     // these were setup from the beginning, it could be different for each volume!!!!
     132                 :            :     // we need a better way to decide/select target and source surfaces
     133                 :            :     // this also assumes that the sourceSurface is fixed between setup and execute
     134         [ +  - ]:          6 :     sourceSurface = gFaces[index_src];
     135         [ +  - ]:          6 :     targetSurface = gFaces[index_tar];
     136         [ +  - ]:         12 :     MEntVector linkingSurfaces;
     137                 :            :     int index_id_src, index_id_tar;
     138         [ +  - ]:          6 :     iGeom::Error g_err = igeom_inst->getIntData(sourceSurface, geom_id_tag, index_id_src);
     139         [ +  - ]:          6 :     IBERRCHK(g_err, "Trouble get the int data for source surface.");
     140         [ +  - ]:          6 :     g_err = igeom_inst->getIntData(targetSurface, geom_id_tag, index_id_tar);
     141         [ +  - ]:          6 :     IBERRCHK(g_err, "Trouble get the int data for target surface.");
     142 [ +  - ][ +  - ]:          6 :     std::cout << " source Global ID: " << index_id_src << " target Global ID: " << index_id_tar << "\n";
         [ +  - ][ +  - ]
                 [ +  - ]
     143                 :            : 
     144         [ +  + ]:         42 :     for (unsigned int i = 0; i < gFaces.size(); i++)
     145                 :            :     {
     146                 :            :       int gid;
     147 [ +  - ][ +  - ]:         36 :       g_err = igeom_inst->getIntData(gFaces[i], geom_id_tag, gid);
     148         [ +  - ]:         36 :       IBERRCHK(g_err, "Trouble get the int data for source surface.");
     149         [ +  - ]:         36 :       std::vector<iBase_EntityHandle> gEdges;
     150 [ +  - ][ +  - ]:         36 :       g_err = igeom_inst->getEntAdj(gFaces[i], iBase_EDGE, gEdges);
     151         [ +  - ]:         36 :       IBERRCHK(g_err, "Trouble get the geometrical edges adjacent to the surface");
     152 [ +  - ][ +  - ]:         36 :       std::cout << " face index " << i << " with ID: " << gid << " has " << gEdges.size() << " edges\n";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     153                 :         36 :     }
     154         [ +  - ]:         12 :     MEntVector surfs;
     155         [ +  - ]:          6 :     me->get_adjacencies(2, surfs);// all surfaces adjacent to the volume
     156         [ +  + ]:         42 :     for (unsigned int i = 0; i < surfs.size(); i++)
     157                 :            :     {
     158                 :            :       int index_id_link;
     159 [ +  - ][ +  - ]:         36 :       g_err = igeom_inst->getIntData(surfs[i]->geom_handle(), geom_id_tag, index_id_link);
                 [ +  - ]
     160         [ +  - ]:         36 :       IBERRCHK(g_err, "Trouble get the int data for linking surface.");
     161 [ +  + ][ +  + ]:         36 :       if ((index_id_link != index_id_src) && (index_id_link != index_id_tar))
     162                 :            :       {
     163         [ +  - ]:         24 :         MEntVector edges;
     164 [ +  - ][ +  - ]:         24 :         surfs[i]->get_adjacencies(1, edges);// all surfaces adjacent to the volume
     165 [ +  - ][ +  - ]:         24 :         std::cout << " linking surface with global ID: " << index_id_link << " has " << edges.size() << " edges\n";
         [ +  - ][ +  - ]
                 [ +  - ]
     166                 :            :         //assert((int)edges.size()==4);
     167                 :            : 
     168 [ +  - ][ +  - ]:         24 :         linkingSurfaces.push_back(surfs[i]);
     169                 :            :       }
     170                 :            :     }
     171                 :            :     // now create a TFI mapping
     172                 :            :     // this will trigger edge meshers for linking edges, and for target surface edges
     173 [ +  - ][ +  - ]:          6 :     TFIMapping *tm = (TFIMapping*) mk_core()->construct_meshop("TFIMapping", linkingSurfaces);
                 [ +  - ]
     174                 :            :     // For now, do not assign any sizing function at all
     175                 :            : //    for (unsigned int i = 0; i < linkingSurfaces.size(); i++)
     176                 :            : //    {
     177                 :            : //      linkingSurfaces[i]->sizing_function_index(sf->core_index());
     178                 :            : //    }
     179 [ +  - ][ +  - ]:          6 :     mk_core()->insert_node(tm, (MeshOp*) this);
     180                 :          6 :   }
     181                 :            : 
     182                 :          6 :   mk_core()->print_graph("AfterOneSetup.eps");
     183                 :            : 
     184                 :            : }
     185                 :            : 
     186                 :            : //---------------------------------------------------------------------------//
     187                 :            : // execute function: generate the all-hex mesh through sweeping from source
     188                 :            : // surface to target surface
     189                 :          6 : void OneToOneSwept::execute_this()
     190                 :            : {
     191                 :            : 
     192 [ +  - ][ +  - ]:         12 :   for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
                 [ +  + ]
     193                 :            :   {
     194         [ +  - ]:          6 :     ModelEnt *me = mit -> first;
     195                 :            :     // maybe it will be decided later?
     196                 :            :     //case 1: if numLayers = 1, then it is not necessary to create any vertices for linking surface, All the vertices have been created by source surface and target surface
     197                 :            :     // bLayers will contain nodes in order, layer by layer
     198         [ +  - ]:          6 :     std::vector<moab::EntityHandle> bLayers;
     199         [ +  - ]:          6 :     BuildLateralBoundaryLayers(me, bLayers);
     200                 :            :     //int sizeBLayer = bLayers.size()/(numLayers+1);
     201         [ +  - ]:          6 :     volume = me->geom_handle();
     202                 :            : 
     203         [ +  - ]:          6 :         TargetSurfProjection(bLayers);// the top layer is the last list of nodes
     204                 :            : 
     205                 :            :     //get the volume mesh entity set
     206 [ +  - ][ +  - ]:          6 :     iRel::Error r_err = mk_core()->irel_pair(me->iRelPairIndex())->getEntSetRelation(me->geom_handle(), 0, volumeSet);
         [ +  - ][ +  - ]
                 [ +  - ]
     207                 :          6 :     IBERRCHK(r_err,
     208         [ +  - ]:          6 :         "Trouble get the volume mesh entity set from the geometrical volume.");
     209                 :            : 
     210 [ +  - ][ +  - ]:         12 :     vector<vector<Vertex> > linkVertexList(numLayers - 1, vector<Vertex> (NodeList.size()));
     211                 :            :     // this will compute the interior points distribution, in each layer
     212         [ +  - ]:          6 :     ProjectInteriorLayers(bLayers, linkVertexList);
     213 [ +  - ][ +  - ]:          6 : std::cout << "Projected interior layers." << std::endl;
     214                 :            : 
     215         [ +  - ]:          6 :     CreateElements(linkVertexList);
     216 [ +  - ][ +  - ]:          6 : std::cout << "Created elements." << std::endl;
     217                 :            : 
     218 [ +  - ][ +  - ]:          6 :     mk_core()->save_mesh("BeforeVolumeImprove.h5m");
     219                 :            : #if HAVE_MESQUITE
     220                 :            :     //MeshImprove meshImpr(mk_core());
     221                 :            :     //meshImpr.VolumeMeshImprove(volumeSet, iBase_REGION);
     222                 :            : #endif
     223 [ +  - ][ +  - ]:          6 :     me->commit_mesh(mit->second, COMPLETE_MESH);
     224                 :          6 :   }
     225                 :            : 
     226                 :          6 : }
     227                 :            : 
     228                 :            : // will also initialize NodeList, which comprises all <Vertex> data on the source sf
     229                 :          6 : void OneToOneSwept::BuildLateralBoundaryLayers(ModelEnt * me, std::vector<moab::EntityHandle> & layers)
     230                 :            : {
     231                 :            :   // start with the source surface
     232                 :            :   //ModelEnt * sourceME = ModelEnt()
     233         [ +  - ]:          6 :   iGeom * igeom_inst = me->igeom_instance();
     234                 :            :   iGeom::Error g_err;
     235                 :          6 :   moab::ErrorCode rval = moab::MB_SUCCESS;
     236                 :            :   int index_id_src, index_id_tar;
     237                 :            : 
     238         [ +  - ]:          6 :   g_err = igeom_inst->getIntData(sourceSurface, geom_id_tag, index_id_src);
     239         [ +  - ]:          6 :   IBERRCHK(g_err, "Trouble get the int data for source surface.");
     240         [ +  - ]:          6 :   g_err = igeom_inst->getIntData(targetSurface, geom_id_tag, index_id_tar);
     241         [ +  - ]:          6 :   IBERRCHK(g_err, "Trouble get the int data for target surface.");
     242                 :            : 
     243                 :          6 :   iBase_TagHandle taghandle = 0;
     244 [ +  - ][ +  - ]:          6 :   iMesh::Error m_err = mk_core()->imesh_instance()->getTagHandle("source", taghandle);
                 [ +  - ]
     245         [ +  + ]:          6 :   if (m_err)
     246                 :            :   {
     247 [ +  - ][ +  - ]:          3 :     m_err = mk_core()->imesh_instance()->createTag("source",
     248         [ +  - ]:          3 :         1, iBase_INTEGER, taghandle);
     249                 :          3 :     IBERRCHK(m_err,
     250         [ +  - ]:          3 :         "Trouble creating the source tag handle in the mesh instance.");
     251                 :            :   }
     252                 :            :   // TODO: If the tag exists, we could verify that the tag is the proper one.
     253                 :            :   // Probably the tag should be put in a namespace, and perhaps it should
     254                 :            :   //   be deleted when we are finished with it.
     255                 :            : 
     256         [ +  - ]:          6 :   moab::Range quadsOnLateralSurfaces;
     257                 :          6 :   ModelEnt * sME = NULL;
     258                 :            : 
     259         [ +  - ]:         12 :   MEntVector surfs;
     260         [ +  - ]:          6 :   me->get_adjacencies(2, surfs); // all surfaces adjacent to the volume
     261                 :            : 
     262         [ +  + ]:         42 :   for (unsigned int i = 0; i < surfs.size(); i++)
     263                 :            :   {
     264                 :            :     int index_id_link;
     265 [ +  - ][ +  - ]:         36 :     g_err = igeom_inst->getIntData(surfs[i]->geom_handle(), geom_id_tag, index_id_link);
                 [ +  - ]
     266         [ +  - ]:         36 :     IBERRCHK(g_err, "Trouble get the int data for linking surface.");
     267 [ +  + ][ +  + ]:         36 :     if ((index_id_link != index_id_src) && (index_id_link != index_id_tar))
     268                 :            :     {
     269 [ +  - ][ +  - ]:         24 :       moab::EntityHandle surfSet = surfs[i]->mesh_handle();
     270                 :            :       // get all nodes from the surface, including the boundary nodes!
     271         [ +  - ]:         24 :       rval = mb->get_entities_by_type(surfSet, moab::MBQUAD, quadsOnLateralSurfaces);
     272 [ -  + ][ #  # ]:         24 :       MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     273                 :            :     }
     274         [ +  + ]:         36 :     if (index_id_link == index_id_src)
     275         [ +  - ]:          6 :       sME = surfs[i];
     276                 :            :   }
     277                 :            :   // the lateral layers will be build from these nodes
     278         [ +  - ]:         12 :   moab::Range nodesOnLateralSurfaces;
     279         [ +  - ]:          6 :   rval = mb->get_connectivity(quadsOnLateralSurfaces, nodesOnLateralSurfaces);
     280 [ -  + ][ #  # ]:          6 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     281                 :            : 
     282                 :            :   // construct NodeList, nodes on source surface
     283                 :            :   // list of node on boundary of source
     284         [ +  - ]:         12 :   std::vector<moab::EntityHandle> bdyNodes;
     285         [ +  - ]:         12 :   std::vector<int> group_sizes;
     286         [ +  - ]:          6 :   sME-> boundary(0, bdyNodes, NULL, &group_sizes);// we do not need the senses, yet
     287                 :            : 
     288                 :          6 :   numLoops = (int) group_sizes.size();
     289                 :          6 :   sizeBLayer = (int) bdyNodes.size();
     290                 :            : 
     291         [ +  - ]:          6 :   std::cout << "Execute one to one swept ....\n";
     292 [ +  - ][ +  - ]:          6 :   std::cout << "Nodes on boundary: " << bdyNodes.size() << "\n";
                 [ +  - ]
     293 [ +  - ][ +  - ]:          6 :   std::cout << "Number of loops: " << group_sizes.size() << "\n";
                 [ +  - ]
     294 [ +  - ][ +  - ]:          6 :   std::cout << "Nodes on lateral surfaces: " << nodesOnLateralSurfaces.size() << "\n";
         [ +  - ][ +  - ]
     295 [ +  - ][ +  - ]:          6 :   std::cout << "Quads on lateral surfaces: " << quadsOnLateralSurfaces.size() << "\n";
         [ +  - ][ +  - ]
     296                 :            : 
     297                 :          6 :   numLayers = 0;
     298         [ +  - ]:          6 :   if (!bdyNodes.empty())
     299         [ +  - ]:          6 :     numLayers = nodesOnLateralSurfaces.size() / bdyNodes.size() - 1;
     300 [ +  - ][ -  + ]:          6 :   if (bdyNodes.size() * (numLayers + 1) != nodesOnLateralSurfaces.size())
     301                 :            :   {
     302 [ #  # ][ #  # ]:          0 :     std::cout << "Major problem: number of total nodes on boundary: " << nodesOnLateralSurfaces.size() << "\n";
         [ #  # ][ #  # ]
     303 [ #  # ][ #  # ]:          0 :     std::cout << " number of nodes in one layer on the boundary:" << bdyNodes.size() << "\n";
                 [ #  # ]
     304 [ #  # ][ #  # ]:          0 :     std::cout << " we expect bdyNodes.size()*(numLayers+1) == nodesOnLateralSurfaces.size(), but " << bdyNodes.size() * (numLayers + 1)
     305 [ #  # ][ #  # ]:          0 :         << " != " << nodesOnLateralSurfaces.size() << "\n";
         [ #  # ][ #  # ]
     306                 :            :   }
     307                 :            :   // start from this list of boundary nodes (on the source)
     308                 :            : 
     309                 :            :   // get all nodes from the source surface
     310         [ +  - ]:         12 :   moab::Range sourceNodes;
     311         [ +  - ]:          6 :   moab::EntityHandle surfSet = sME->mesh_handle();
     312                 :            :   // get all nodes from the surface, including the boundary nodes!
     313         [ +  - ]:         12 :   moab::Range quads;
     314         [ +  - ]:          6 :   rval = mb->get_entities_by_type(surfSet, moab::MBQUAD, quads);
     315 [ -  + ][ #  # ]:          6 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     316                 :            :   // we do not really care about corners, only about boundary
     317         [ +  - ]:          6 :   rval = mb->get_connectivity(quads, sourceNodes);
     318 [ -  + ][ #  # ]:          6 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     319                 :            : 
     320 [ +  - ][ +  - ]:          6 :   NodeList.resize(sourceNodes.size());
     321                 :          6 :   int i = 0;
     322 [ +  - ][ +  - ]:       1173 :   for (moab::Range::iterator it = sourceNodes.begin(); it != sourceNodes.end(); it++, i++)
         [ +  - ][ +  - ]
                 [ +  + ]
     323                 :            :   {
     324         [ +  - ]:       1167 :     moab::EntityHandle node = *it;
     325 [ +  - ][ +  - ]:       1167 :     NodeList[i].gVertexHandle = (iBase_EntityHandle) sourceNodes[i];
     326         [ +  - ]:       1167 :     NodeList[i].index = i;
     327                 :            : 
     328 [ +  - ][ +  - ]:       1167 :     rval = mb->get_coords(&node, 1, &(NodeList[i].xyz[0]));
                 [ +  - ]
     329 [ -  + ][ #  # ]:       1167 :     MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     330         [ +  - ]:       1167 :     NodeList[i].onBoundary = false;
     331                 :            : 
     332                 :            :     //set the int data to the entity
     333 [ +  - ][ +  - ]:       1167 :     m_err = mk_core()->imesh_instance()->setIntData(NodeList[i].gVertexHandle, taghandle, NodeList[i].index);
         [ +  - ][ +  - ]
                 [ +  - ]
     334         [ +  - ]:       1167 :     IBERRCHK(m_err, "Trouble set the int value for nodes in the mesh instance.");
     335                 :            :   }
     336                 :            :   // now loop over the boundary and mark the boundary nodes as such
     337         [ +  + ]:        444 :   for (unsigned int j = 0; j < bdyNodes.size(); j++)
     338                 :            :   {
     339         [ +  - ]:        438 :     iBase_EntityHandle node = (iBase_EntityHandle) bdyNodes[j];
     340                 :            :     int index;
     341 [ +  - ][ +  - ]:        438 :     m_err = mk_core()->imesh_instance()->getIntData(node, taghandle, index);
                 [ +  - ]
     342         [ +  - ]:        438 :     IBERRCHK(m_err, "Trouble set the int value for nodes in the mesh instance.");
     343         [ +  - ]:        438 :     NodeList[index].onBoundary = true;// some could be corners, but it is not that important
     344                 :            :   }
     345                 :            : 
     346                 :            :   // process faces on the source
     347 [ +  - ][ +  - ]:          6 :   FaceList.resize(quads.size());// quads is actually a range....
     348                 :            : 
     349 [ +  - ][ +  + ]:        951 :   for (unsigned int i = 0; i < quads.size(); i++)
     350                 :            :   {
     351         [ +  - ]:        945 :     iBase_EntityHandle currentFace = (iBase_EntityHandle) quads[i];//
     352         [ +  - ]:        945 :     FaceList[i].gFaceHandle = currentFace;
     353                 :            :     //FaceList[i].index = i;
     354                 :            : 
     355                 :            :     //get the nodes on the face elements
     356         [ +  - ]:        945 :     std::vector<iBase_EntityHandle> Nodes;
     357 [ +  - ][ +  - ]:        945 :     m_err = mk_core()->imesh_instance()->getEntAdj(currentFace, iBase_VERTEX, Nodes);
                 [ +  - ]
     358         [ +  - ]:        945 :     IBERRCHK(m_err, "Trouble get the adjacent nodes from mesh face entity.");
     359                 :            : 
     360 [ +  - ][ +  - ]:        945 :     FaceList[i].connect.resize(Nodes.size());
     361         [ +  + ]:       4725 :     for (unsigned int j = 0; j < Nodes.size(); j++)
     362                 :            :     {
     363                 :       3780 :       int tmpIndex = -1;
     364 [ +  - ][ +  - ]:       3780 :       m_err = mk_core()->imesh_instance()->getIntData(Nodes[j], taghandle, tmpIndex);
         [ +  - ][ +  - ]
     365         [ +  - ]:       3780 :       IBERRCHK(m_err, "Trouble get the int data from node handle.");
     366                 :            : 
     367 [ +  - ][ +  - ]:       3780 :       FaceList[i].connect[j] = &NodeList[tmpIndex];// why not store tmp Index directly?
                 [ +  - ]
     368                 :            :     }
     369 [ +  - ][ +  - ]:        945 :         m_err = mk_core()->imesh_instance()->setIntData(currentFace, taghandle, i);
                 [ +  - ]
     370         [ +  - ]:        945 :         IBERRCHK(m_err, "Trouble set the int data for quads on the source surface.");
     371                 :            : 
     372                 :            :    /* m_err = mk_core()->imesh_instance()->setIntData(currentFace, taghandle, i);
     373                 :            :     IBERRCHK(m_err, "Trouble set the int data for quad mesh on the source surface.");*/
     374                 :        945 :   }
     375                 :            : 
     376 [ +  - ][ +  - ]:          6 :   std::copy(bdyNodes.begin(), bdyNodes.end(), std::back_inserter(layers));
     377                 :            : 
     378                 :            :   // mark all of the boundary nodes
     379         [ +  - ]:          6 :   markedMoabEnts.insert(bdyNodes.begin(), bdyNodes.end());
     380                 :            : 
     381         [ +  + ]:         25 :   for (int layer = 1; layer <= numLayers; layer++) // layer with index 0 is at the bottom/source
     382                 :            :   {
     383                 :         19 :     int start_index = 0;//this is the start index in group
     384         [ +  + ]:         44 :     for (unsigned int k = 0; k < group_sizes.size(); k++)
     385                 :            :     {
     386                 :            :       // first group starts at index 0, the rest are accumulated
     387         [ +  + ]:         25 :       if (k > 0)
     388         [ +  - ]:          6 :         start_index += group_sizes[k - 1];
     389         [ +  - ]:         25 :       moab::EntityHandle node1 = layers[(layer - 1) * sizeBLayer + start_index];
     390         [ +  - ]:         25 :       moab::EntityHandle node2 = layers[(layer - 1) * sizeBLayer + start_index + 1];
     391                 :            :       moab::EntityHandle node3, node4;
     392                 :            :       /*
     393                 :            :        *     node3 -- node4 -->  (next layer)
     394                 :            :        *       |        |
     395                 :            :        *     node1 -- node2 ---> (guide layer)
     396                 :            :        */
     397         [ +  - ]:         25 :       rval = NodeAbove(node1, node2, quadsOnLateralSurfaces, node3, node4);
     398 [ -  + ][ #  # ]:         25 :       MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     399                 :            :       // check that node3 and node4 are not yet marked
     400 [ +  - ][ +  - ]:         25 :       if (markedMoabEnts.find(node3) != markedMoabEnts.end())
                 [ -  + ]
     401 [ #  # ][ #  # ]:          0 :         MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     402 [ +  - ][ +  - ]:         25 :       if (markedMoabEnts.find(node4) != markedMoabEnts.end())
                 [ -  + ]
     403 [ #  # ][ #  # ]:          0 :         MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     404         [ +  - ]:         25 :       layers.push_back(node3);//start of a new layer
     405         [ +  - ]:         25 :       layers.push_back(node4);//node above node 2
     406                 :            :       // mark node3 and node4
     407         [ +  - ]:         25 :       markedMoabEnts.insert(node3);
     408         [ +  - ]:         25 :       markedMoabEnts.insert(node4);
     409                 :            :       // we have at least 2 nodes in every loop, otherwise we are in deep trouble
     410                 :            :       //start
     411                 :         25 :       int currentIndex = start_index + 2;
     412 [ +  - ][ +  + ]:       1221 :       while (currentIndex < start_index + group_sizes[k])
     413                 :            :       {
     414                 :       1196 :         node1 = node2;
     415         [ +  - ]:       1196 :         node2 = layers[(layer - 1) * sizeBLayer + currentIndex];// actually, the previous layer
     416                 :       1196 :         node3 = node4;
     417         [ +  - ]:       1196 :         rval = FourthNodeInQuad(node1, node2, node3, quadsOnLateralSurfaces, node4);
     418 [ -  + ][ #  # ]:       1196 :         MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     419 [ +  - ][ +  - ]:       1196 :         if (markedMoabEnts.find(node4) != markedMoabEnts.end())
                 [ -  + ]
     420 [ #  # ][ #  # ]:          0 :           MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     421         [ +  - ]:       1196 :         layers.push_back(node4);
     422         [ +  - ]:       1196 :         markedMoabEnts.insert(node4);
     423                 :       1196 :         currentIndex++;
     424                 :            :       }
     425                 :            :     }// end group
     426                 :            :   }// end layer
     427         [ +  + ]:         31 :   for (int lay = 0; lay <= numLayers; lay++)
     428                 :            :   {
     429 [ +  - ][ +  - ]:         25 :     std::cout << "layer : " << lay << "\n";
                 [ +  - ]
     430         [ +  + ]:       1709 :     for (int i = 0; i < sizeBLayer; i++)
     431                 :            :     {
     432 [ +  - ][ +  - ]:       1684 :       std::cout << " " << layers[lay * sizeBLayer + i];
                 [ +  - ]
     433         [ +  + ]:       1684 :       if (i % 10 == 9)
     434         [ +  - ]:        163 :         std::cout << "\n";
     435                 :            :     }
     436         [ +  - ]:         25 :     std::cout << "\n";
     437                 :          6 :   }
     438                 :          6 : }
     439                 :            : 
     440                 :         25 : moab::ErrorCode OneToOneSwept::NodeAbove(moab::EntityHandle node1, moab::EntityHandle node2, moab::Range & latQuads,
     441                 :            :     moab::EntityHandle & node3, moab::EntityHandle & node4)
     442                 :            : {
     443                 :            :   // look for node above node 1 in an unused quad
     444                 :         25 :   moab::EntityHandle nds[2] = { node1, node2 };
     445                 :            :   // find all quads connected to these 2 nodes; find one in the range that is not used
     446         [ +  - ]:         25 :   moab::Range adj_entities;
     447         [ +  - ]:         25 :   moab::ErrorCode rval = mb->get_adjacencies(nds, 2, 2, false, adj_entities);
     448 [ -  + ][ #  # ]:         25 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     449                 :            :   // default is -1
     450                 :         25 :   moab::EntityHandle nextQuad = 0;// null
     451 [ +  - ][ +  - ]:         56 :   for (unsigned int i = 0; i < adj_entities.size(); i++)
     452                 :            :   {
     453 [ +  - ][ +  - ]:        152 :     if ((markedMoabEnts.find(adj_entities[i]) == markedMoabEnts.end()) &&
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
           [ +  +  #  #  
             #  #  #  # ]
     454 [ +  - ][ +  - ]:         96 :         (latQuads.find(adj_entities[i]) != latQuads.end()))
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
           [ #  #  #  # ]
     455                 :            :     {
     456                 :            :       // the quadrilateral is not marked but is on the lateral/linking surface
     457         [ +  - ]:         25 :       nextQuad = adj_entities[i];
     458                 :         25 :       break;
     459                 :            :     }
     460                 :            :   }
     461         [ -  + ]:         25 :   if (0 == nextQuad)
     462 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     463                 :            : 
     464                 :            :   // decide on which side are nodes 1 and 2, then get the opposite side
     465                 :         25 :   const moab::EntityHandle * conn4 = NULL;
     466                 :            :   int nnodes;
     467         [ +  - ]:         25 :   rval = mb->get_connectivity(nextQuad, conn4, nnodes);
     468 [ -  + ][ #  # ]:         25 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     469                 :         25 :   int index1 = -1;
     470         [ +  - ]:         37 :   for (index1 = 0; index1 < 4; index1++)
     471         [ +  + ]:         37 :     if (node1 == conn4[index1])
     472                 :         25 :       break;
     473         [ -  + ]:         25 :   if (4 == index1)
     474 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     475         [ +  + ]:         25 :   if (node2 == conn4[(index1 + 1) % 4]) // quad is oriented node1, node2, node4, node3
     476                 :            :   {
     477                 :         19 :     node3 = conn4[(index1 + 3) % 4];
     478                 :            :   }
     479         [ +  - ]:          6 :   else if (node2 == conn4[(index1 +3) % 4]) // quad is oriented node2, node1, node3, node4
     480                 :            :   {
     481                 :          6 :     node3 = conn4[(index1 + 1) % 4];
     482                 :            :   }
     483                 :            :   else
     484 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);// something is really wrong
                 [ #  # ]
     485                 :         25 :   node4 = conn4[(index1 + 2) % 4];
     486                 :            : 
     487                 :            :   // mark the quad to be sure not to use it again
     488         [ +  - ]:         25 :   markedMoabEnts.insert(nextQuad);
     489                 :            : 
     490                 :         25 :   return moab::MB_SUCCESS;
     491                 :            : }
     492                 :            : 
     493                 :       1196 : moab::ErrorCode OneToOneSwept::FourthNodeInQuad(moab::EntityHandle node1, moab::EntityHandle node2, moab::EntityHandle node3,
     494                 :            :     moab::Range & latQuads, moab::EntityHandle & node4)
     495                 :            : {
     496                 :            :   // look for the fourth node
     497                 :       1196 :   moab::EntityHandle nds[3] = { node1, node2, node3 };
     498                 :            :   // find all quads connected to these 3 nodes; find one in the range that is not used
     499         [ +  - ]:       1196 :   moab::Range adj_entities;
     500         [ +  - ]:       1196 :   moab::ErrorCode rval = mb->get_adjacencies(nds, 3, 2, false, adj_entities);
     501 [ -  + ][ #  # ]:       1196 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     502                 :            : 
     503                 :       1196 :   moab::EntityHandle nextQuad = 0;// null
     504 [ +  - ][ +  - ]:       1196 :   for (unsigned int i = 0; i < adj_entities.size(); i++)
     505                 :            :   {
     506 [ +  - ][ +  - ]:       3588 :     if ((markedMoabEnts.find(adj_entities[i]) == markedMoabEnts.end()) &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ +  -  #  #  
             #  #  #  # ]
     507 [ +  - ][ +  - ]:       2392 :         (latQuads.find(adj_entities[i]) != latQuads.end()))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ #  #  #  # ]
     508                 :            :     {
     509                 :            :       // the quadrilateral is not marked but is on the lateral/linking surface
     510         [ +  - ]:       1196 :       nextQuad = adj_entities[i];
     511                 :       1196 :       break;
     512                 :            :     }
     513                 :            :   }
     514         [ -  + ]:       1196 :   if (0 == nextQuad)
     515 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     516                 :            : 
     517                 :            :   // decide on which side are nodes 1 and 2, then get the opposite side
     518                 :       1196 :   const moab::EntityHandle * conn4 = NULL;
     519                 :            :   int nnodes;
     520         [ +  - ]:       1196 :   rval = mb->get_connectivity(nextQuad, conn4, nnodes);
     521 [ -  + ][ #  # ]:       1196 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     522                 :            : 
     523                 :       1196 :   node4 = 0;
     524         [ +  - ]:       3100 :   for (int index = 0; index < 4; index++)
     525                 :            :   {
     526                 :       3100 :     moab::EntityHandle c4 = conn4[index];
     527 [ +  + ][ +  + ]:       3100 :     if (node1 != c4 && node2 != c4 && node3 != c4)
                 [ +  + ]
     528                 :            :     {
     529                 :       1196 :       node4 = c4;
     530                 :       1196 :       break;
     531                 :            :     }
     532                 :            :   }
     533         [ -  + ]:       1196 :   if (0 == node4)
     534 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     535                 :            : 
     536                 :            :   // mark the quad to be sure not to use it again
     537         [ +  - ]:       1196 :   markedMoabEnts.insert(nextQuad);
     538                 :            : 
     539                 :       1196 :   return moab::MB_SUCCESS;
     540                 :            : 
     541                 :            : }
     542                 :            : #ifdef HAVE_ARMADILLO
     543                 :            : void OneToOneSwept::SurfMeshHarmonic(iBase_EntityHandle vol, vector<iBase_EntityHandle> &newNodehandle)
     544                 :            : {
     545                 :            :         
     546                 :            :         SurfProHarmonicMap surf_pro(mk_core(), sourceSurface, targetSurface, vol);
     547                 :            :         surf_pro.match();
     548                 :            :         surf_pro.setMeshData(NodeList, TVertexList, FaceList);
     549                 :            :         surf_pro.projection();
     550                 :            :         surf_pro.getMeshData(TVertexList);
     551                 :            : 
     552                 :            :         iMesh::Error m_err;
     553                 :            :         for (unsigned int i = 0; i < TVertexList.size(); i++){
     554                 :            :                 if (TVertexList[i].onBoundary)
     555                 :            :                         continue;
     556                 :            :                 m_err = mk_core()->imesh_instance()->createVtx(TVertexList[i].xyz[0], TVertexList[i].xyz[1], TVertexList[i].xyz[2], TVertexList[i].gVertexHandle);
     557                 :            :                 IBERRCHK(m_err, "Trouble create a mesh nodes on the target surface!");
     558                 :            :                 newNodehandle.push_back(TVertexList[i].gVertexHandle);
     559                 :            :         }       
     560                 :            : }
     561                 :            : #endif
     562                 :            : 
     563                 :          0 : bool OneToOneSwept::isConcave()
     564                 :            : {
     565                 :            :         //use the quad mesh on the source surface to determine whether it is concave or not
     566                 :          0 :         iBase_TagHandle taghandle = 0;
     567 [ #  # ][ #  # ]:          0 :         iMesh::Error m_err = mk_core()->imesh_instance()->getTagHandle("source", taghandle);
                 [ #  # ]
     568         [ #  # ]:          0 :         IBERRCHK(m_err, "Trouble get the tag handle in the mesh instance.");
     569 [ #  # ][ #  # ]:          0 :         for (std::vector<Vertex>::iterator it = NodeList.begin(); it != NodeList.end(); it++){
                 [ #  # ]
     570 [ #  # ][ #  # ]:          0 :                 if (!it->onBoundary)
     571                 :          0 :                         continue;
     572                 :            :                 //get the adjacent quads around a vertex
     573                 :          0 :                 double angle = 0.0;
     574         [ #  # ]:          0 :                 std::vector<iBase_EntityHandle> adj_quads;
     575 [ #  # ][ #  # ]:          0 :                 m_err = mk_core()->imesh_instance()->getEntAdj(it->gVertexHandle, iBase_FACE, adj_quads);
         [ #  # ][ #  # ]
     576         [ #  # ]:          0 :                 IBERRCHK(m_err, "Trouble get the adjacent quads around a vertex!");
     577         [ #  # ]:          0 :                 for (unsigned int i = 0; i < adj_quads.size(); i++){
     578                 :          0 :                         int face_index = -1;
     579 [ #  # ][ #  # ]:          0 :                         m_err = mk_core()->imesh_instance()->getIntData(adj_quads[i], taghandle, face_index);
         [ #  # ][ #  # ]
     580         [ #  # ]:          0 :                         if (m_err) continue;//this is a quad entity from the linking surface
     581                 :          0 :                         int node_index = 0, pre_index, next_index;
     582         [ #  # ]:          0 :                         for (int j = 0; j < 4; j++)
     583 [ #  # ][ #  # ]:          0 :                                 if (FaceList[face_index].connect[j]->index == it->index){
         [ #  # ][ #  # ]
     584                 :          0 :                                         node_index = j;
     585                 :          0 :                                         break;
     586                 :            :                                 }
     587 [ #  # ][ #  # ]:          0 :                         Vector3D v1(0.0), v2(0.0);
     588 [ #  # ][ #  # ]:          0 :                         pre_index = (FaceList[face_index].getVertex((node_index+4-1)%4))->index;
     589 [ #  # ][ #  # ]:          0 :                         next_index = (FaceList[face_index].getVertex((node_index+1)%4))->index;
     590 [ #  # ][ #  # ]:          0 :                         v1 = NodeList[pre_index].xyz - it->xyz;
         [ #  # ][ #  # ]
     591 [ #  # ][ #  # ]:          0 :                         v2 = NodeList[next_index].xyz - it->xyz;
         [ #  # ][ #  # ]
     592 [ #  # ][ #  # ]:          0 :                         double dotproduct = v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     593 [ #  # ][ #  # ]:          0 :                         angle += acos(dotproduct/sqrt((v1[0]*v1[0]+v1[1]*v1[1]+v1[2]*v1[2])*(v2[0]*v2[0]+v2[1]*v2[1]+v2[2]*v2[2])));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     594                 :            :                 }
     595         [ #  # ]:          0 :                 if (angle > M_PI){
     596         [ #  # ]:          0 :                         return true;    
     597                 :            :                 }
     598                 :          0 :         }
     599                 :            : 
     600                 :          0 :         return false;   
     601                 :            : }
     602                 :            : 
     603                 :            : 
     604                 :            : //****************************************************************************//
     605                 :            : // function   : TargetSurfProjection
     606                 :            : // Author     : Shengyong Cai
     607                 :            : // Date       : Feb 15, 2011
     608                 :            : // Description: map the mesh on the source surface to the target surface
     609                 :            : //***************************************************************************//
     610                 :          6 : int OneToOneSwept::TargetSurfProjection(std::vector<moab::EntityHandle> & bLayers)
     611                 :            : {
     612                 :            :   iMesh::Error m_err;
     613                 :            :   //iGeom::Error g_err;
     614                 :            :   iRel::Error r_err;
     615                 :            :   moab::ErrorCode rval;
     616                 :            : 
     617         [ +  - ]:          6 :   MEntVector surfs;
     618 [ +  - ][ +  - ]:          6 :   mk_core()->get_entities_by_dimension(2, surfs);
     619                 :          6 :   ModelEnt *target_surf = 0;
     620         [ +  - ]:         56 :   for (unsigned int i = 0; i < surfs.size(); i++)
     621                 :            :   {
     622                 :            : 
     623 [ +  - ][ +  - ]:         56 :     if (surfs[i]->geom_handle() == targetSurface)
                 [ +  + ]
     624                 :            :     {
     625         [ +  - ]:          6 :       target_surf = surfs[i];
     626                 :          6 :       break;
     627                 :            :     }
     628                 :            :   }
     629         [ +  - ]:          6 :   int irelIndx = target_surf->iRelPairIndex();
     630 [ +  - ][ +  - ]:          6 :   iGeom * igeom_inst = mk_core()->igeom_instance(target_surf->iGeomIndex());
                 [ +  - ]
     631                 :            :   // we could have got it from model tag, too
     632                 :            :   // something along this:
     633                 :            :   // err = igeom_instance(geom_index)->getData(*eit, iGeomModelTags[geom_index], &this_me);
     634                 :            : 
     635         [ +  - ]:          6 :   TVertexList.resize(NodeList.size());
     636                 :            :   // make everything not on boundary, first; the true boundary flag will be set later
     637         [ +  + ]:       1173 :   for (unsigned int i = 0; i < TVertexList.size(); i++)
     638                 :            :   {
     639         [ +  - ]:       1167 :     TVertexList[i].onBoundary = false;
     640                 :            :   }
     641                 :            : 
     642                 :          6 :   iBase_TagHandle taghandle_tar = 0; 
     643 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->getTagHandle("TargetMesh",
     644         [ +  - ]:          6 :       taghandle_tar);
     645         [ +  + ]:          6 :   if (m_err)
     646                 :            :   {
     647 [ +  - ][ +  - ]:          3 :     m_err = mk_core()->imesh_instance()->createTag("TargetMesh",
     648         [ +  - ]:          3 :         1, iBase_INTEGER, taghandle_tar);
     649                 :          3 :     IBERRCHK(m_err,
     650         [ +  - ]:          3 :         "Trouble create the target mesh tag handle in the mesh instance.");
     651                 :            :   }
     652                 :            :   // TODO: If the tag exists, we could verify that the tag is the proper one.
     653                 :            :   // Probably the tag should be put in a namespace, and perhaps it should
     654                 :            :   //   be deleted when we are finished with it.
     655                 :            : 
     656                 :          6 :   iBase_TagHandle taghandle = 0;
     657 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->getTagHandle("source", taghandle);
                 [ +  - ]
     658         [ +  - ]:          6 :   IBERRCHK(m_err, "Trouble get tag handle of the source surface.");
     659                 :            : 
     660                 :            :   // we know the first layer of nodes (on the source)
     661                 :            :   //
     662                 :            :   // the first 0 , 1, ..., sizeBlayer - 1 are on bottom, were bdyNodes before
     663                 :            :   //
     664         [ +  + ]:        444 :   for (int i = 0; i < sizeBLayer; i++)
     665                 :            :   {
     666         [ +  - ]:        438 :     iBase_EntityHandle sBNode = (iBase_EntityHandle) bLayers[i];
     667                 :            :     int index;
     668 [ +  - ][ +  - ]:        438 :     m_err = mk_core()->imesh_instance()->getIntData(sBNode, taghandle, index);
                 [ +  - ]
     669         [ +  - ]:        438 :     IBERRCHK(m_err, "Trouble get the int value for nodes in the mesh instance.");
     670         [ +  - ]:        438 :     TVertexList[index].onBoundary = true;// some could be corners, but it is not that important
     671         [ +  - ]:        438 :     moab::EntityHandle topNode = bLayers[numLayers * sizeBLayer + i];// node right above
     672                 :        438 :     iBase_EntityHandle tBNode = (iBase_EntityHandle) topNode;// it is right above node i in loop
     673         [ +  - ]:        438 :     TVertexList[index].gVertexHandle = tBNode;
     674                 :            :     // now get the coordinates of the tBNode (node on boundary of target)
     675 [ +  - ][ +  - ]:        438 :     rval = mb->get_coords(&topNode, 1, &(TVertexList[index].xyz[0]));
                 [ +  - ]
     676 [ -  + ][ #  # ]:        438 :     MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     677                 :            : 
     678                 :            :   }
     679                 :            : 
     680                 :            :   iBase_EntitySetHandle entityset; //this entityset is for storing the inner nodes on the target surface
     681         [ +  - ]:         12 :   vector<iBase_EntityHandle> newNodehandle;
     682                 :            : 
     683 [ +  - ][ +  - ]:          6 :   r_err = mk_core()->irel_pair(irelIndx)->getEntSetRelation(targetSurface, 0, entityset);
                 [ +  - ]
     684         [ -  + ]:          6 :   if (r_err) //there is no entityset associated with targetSurface; this should be an error
     685                 :            :   {
     686 [ #  # ][ #  # ]:          0 :     m_err = mk_core()->imesh_instance()->createEntSet(1, entityset);
                 [ #  # ]
     687         [ #  # ]:          0 :     IBERRCHK(m_err, "Trouble create the entity set");
     688                 :            :   }
     689                 :            : 
     690                 :            :  // bool condition_harmonic = isConcave();
     691                 :          6 :   bool is_exe_harmonic = false;
     692                 :            : #ifdef HAVE_ARMADILLO
     693                 :            :   //target surface mesh projection based on harmonic mapping
     694                 :            :   if (condition_harmonic){
     695                 :            :         is_exe_harmonic = true;
     696                 :            :         SurfMeshHarmonic(volume, newNodehandle);
     697                 :            :   }
     698                 :            : #endif
     699                 :            : 
     700         [ +  - ]:          6 :    if (!is_exe_harmonic){
     701                 :            :           /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     702                 :            :           // Based on the transformation in the physical space, project the mesh nodes on the source surface to the target surface
     703                 :            :           /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     704 [ +  - ][ +  - ]:          6 :           Vector3D sPtsCenter(0.0), tPtsCenter(0.0);
     705 [ +  - ][ +  - ]:         12 :           std::vector<Vector3D> sBndNodes(sizeBLayer), tBndNodes(sizeBLayer);
     706                 :          6 :           int num_pts = 0;
     707                 :            :           //calculate the barycenters for the source and target boundaries
     708         [ +  + ]:       1173 :           for (unsigned int i = 0; i < NodeList.size(); i++)
     709                 :            :           {
     710 [ +  - ][ +  + ]:       1167 :                 if (NodeList[i].onBoundary)
     711                 :            :                 {
     712 [ +  - ][ +  - ]:        438 :                   sPtsCenter += NodeList[i].xyz;
     713 [ +  - ][ +  - ]:        438 :                   tPtsCenter += TVertexList[i].xyz;
     714 [ +  - ][ +  - ]:        438 :                   sBndNodes[num_pts] = NodeList[i].xyz;
     715 [ +  - ][ +  - ]:        438 :                   tBndNodes[num_pts] = TVertexList[i].xyz;
     716                 :        438 :                   num_pts++;
     717                 :            :                 }
     718                 :            :           }
     719         [ -  + ]:          6 :           if (sizeBLayer != num_pts)
     720 [ #  # ][ #  # ]:          0 :                 MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     721 [ +  - ][ +  - ]:          6 :           sPtsCenter = sPtsCenter / num_pts;
     722 [ +  - ][ +  - ]:          6 :           tPtsCenter = tPtsCenter / num_pts;
     723                 :            :           //done with the barycenter calculation
     724                 :            : 
     725                 :            :           // compute transformation matrix from source boundary to target boundary
     726         [ +  - ]:          6 :           Matrix3D transMatrix;
     727         [ +  - ]:          6 :           computeTransformationFromSourceToTarget(sBndNodes, sPtsCenter, tBndNodes, tPtsCenter, transMatrix);
     728                 :            : 
     729                 :            :           //calculate the inner nodes on the target surface
     730         [ +  + ]:       1173 :           for (unsigned int i = 0; i < NodeList.size(); i++)
     731                 :            :           {
     732 [ +  - ][ +  + ]:       1167 :                 if (!NodeList[i].onBoundary)
     733                 :            :                 {
     734         [ +  - ]:        729 :                   Vector3D xyz;
     735 [ +  - ][ +  - ]:        729 :                   xyz = transMatrix * (NodeList[i].xyz - 2 * sPtsCenter + tPtsCenter)+sPtsCenter;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     736                 :            : 
     737 [ +  - ][ +  - ]:        729 :                   iGeom::Error g_err = igeom_inst->getEntClosestPt(targetSurface, xyz[0], xyz[1], xyz[2], TVertexList[i].xyz[0],
         [ +  - ][ +  - ]
                 [ +  - ]
     738 [ +  - ][ +  - ]:       1458 :                       TVertexList[i].xyz[1], TVertexList[i].xyz[2]);
         [ +  - ][ +  - ]
                 [ +  - ]
     739         [ +  - ]:        729 :                   IBERRCHK(g_err, "Trouble get the closest point on the targets surface.");
     740                 :            : 
     741                 :            :                   //create the node entities
     742 [ +  - ][ +  - ]:        729 :                   iMesh::Error m_err = mk_core()->imesh_instance()->createVtx(TVertexList[i].xyz[0], TVertexList[i].xyz[1],
         [ +  - ][ +  - ]
     743 [ +  - ][ +  - ]:       1458 :                       TVertexList[i].xyz[2], TVertexList[i].gVertexHandle);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     744         [ +  - ]:        729 :                   IBERRCHK(m_err, "Trouble create the node entity.");
     745         [ +  - ]:        729 :                   TVertexList[i].onBoundary = false;
     746 [ +  - ][ +  - ]:        729 :                   newNodehandle.push_back(TVertexList[i].gVertexHandle);
     747                 :            :                 }
     748                 :          6 :           }
     749                 :            :   }
     750                 :            :   //add the inner nodes to the entityset
     751 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->addEntArrToSet(&newNodehandle[0], newNodehandle.size(), entityset);
         [ +  - ][ +  - ]
     752         [ +  - ]:          6 :   IBERRCHK(m_err, "Trouble add an array of nodes to the entityset.");
     753                 :            : 
     754                 :            :   //until now, all the nodes have been generated on the target surface
     755                 :            : 
     756                 :            :   // we need to decide the orientation with respect to the faces on the source (which are oriented correctly)
     757                 :            :   // look at the first 2 nodes in the boundary, in target
     758                 :          6 :   int sense_out = 1;
     759         [ +  - ]:         12 :   std::vector<moab::EntityHandle> bdyTNodes;
     760         [ +  - ]:         12 :   std::vector<int> group_sizes;
     761         [ +  - ]:          6 :   target_surf-> boundary(0, bdyTNodes, NULL, &group_sizes);// we do not need the senses, yet. Or do we?
     762                 :            :   // find the first node and second node in the bLayers[] list corresponding to the top
     763 [ +  - ][ +  - ]:          6 :   moab::EntityHandle node1 = bdyTNodes[1], node2 = bdyTNodes[2];
     764                 :          6 :   int index = -1;
     765         [ +  - ]:        154 :   for (index = 0; index < sizeBLayer; index++)
     766                 :            :   {
     767 [ +  - ][ +  + ]:        154 :     if (bLayers[numLayers * sizeBLayer + index] == node1)
     768                 :          6 :       break;
     769                 :            :   }
     770         [ -  + ]:          6 :   if (index == sizeBLayer)
     771 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);
                 [ #  # ]
     772                 :            : 
     773                 :          6 :   int prevIndex = (index + sizeBLayer -1) % sizeBLayer;
     774                 :          6 :   int nextIndex = (index + 1) % sizeBLayer;
     775 [ +  - ][ -  + ]:          6 :   if (bLayers[numLayers * sizeBLayer + prevIndex] == node2)
     776                 :          0 :     sense_out = -1;
     777 [ +  - ][ +  - ]:          6 :   else if (bLayers[numLayers * sizeBLayer + nextIndex] == node2)
     778                 :          6 :     sense_out = 1;
     779                 :            :   else
     780 [ #  # ][ #  # ]:          0 :     MBERRCHK(moab::MB_FAILURE, mb);// serious error in the logic, can't decide orientation
                 [ #  # ]
     781                 :            : 
     782                 :            : 
     783                 :            :   //create the quadrilateral elements on the target surface
     784         [ +  - ]:         12 :   vector<iBase_EntityHandle> mFaceHandle(FaceList.size());
     785         [ +  - ]:         12 :   vector<iBase_EntityHandle> connect(FaceList.size() * 4);
     786         [ +  + ]:        951 :   for (unsigned int i = 0; i < FaceList.size(); i++)
     787                 :            :   {
     788         [ -  + ]:        945 :     if (sense_out < 0)
     789                 :            :     {
     790 [ #  # ][ #  # ]:          0 :       connect[4 * i + 0] = TVertexList[(FaceList[i].getVertex(0))->index].gVertexHandle;
         [ #  # ][ #  # ]
     791 [ #  # ][ #  # ]:          0 :       connect[4 * i + 1] = TVertexList[(FaceList[i].getVertex(3))->index].gVertexHandle;
         [ #  # ][ #  # ]
     792 [ #  # ][ #  # ]:          0 :       connect[4 * i + 2] = TVertexList[(FaceList[i].getVertex(2))->index].gVertexHandle;
         [ #  # ][ #  # ]
     793 [ #  # ][ #  # ]:          0 :       connect[4 * i + 3] = TVertexList[(FaceList[i].getVertex(1))->index].gVertexHandle;
         [ #  # ][ #  # ]
     794                 :            :     }
     795                 :            :     else
     796                 :            :     {
     797 [ +  - ][ +  - ]:        945 :       connect[4 * i + 0] = TVertexList[(FaceList[i].getVertex(0))->index].gVertexHandle;
         [ +  - ][ +  - ]
     798 [ +  - ][ +  - ]:        945 :       connect[4 * i + 1] = TVertexList[(FaceList[i].getVertex(1))->index].gVertexHandle;
         [ +  - ][ +  - ]
     799 [ +  - ][ +  - ]:        945 :       connect[4 * i + 2] = TVertexList[(FaceList[i].getVertex(2))->index].gVertexHandle;
         [ +  - ][ +  - ]
     800 [ +  - ][ +  - ]:        945 :       connect[4 * i + 3] = TVertexList[(FaceList[i].getVertex(3))->index].gVertexHandle;
         [ +  - ][ +  - ]
     801                 :            :     }
     802                 :            : 
     803                 :            :   }
     804 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->createEntArr(iMesh_QUADRILATERAL, &connect[0], connect.size(), &mFaceHandle[0]);
         [ +  - ][ +  - ]
                 [ +  - ]
     805         [ +  - ]:          6 :   IBERRCHK(m_err, "Trouble create the quadrilateral mesh.");
     806                 :            : 
     807                 :            :   //add the inner face elements to the entityset
     808 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->addEntArrToSet(&mFaceHandle[0], FaceList.size(), entityset);
         [ +  - ][ +  - ]
     809         [ +  - ]:          6 :   IBERRCHK(m_err, "Trouble add an array of quadrilateral entities to the entity set.");
     810                 :            : 
     811 [ +  - ][ +  - ]:          6 :   mk_core()->save_mesh("BeforeHex.vtk");
     812                 :            : #ifdef HAVE_MESQUITE
     813                 :            : 
     814         [ +  - ]:          6 :   SurfMeshOptimization();
     815                 :            : 
     816                 :            : #endif
     817                 :            : 
     818                 :          6 :   return 1;
     819                 :            : }
     820                 :            : // input: list of nodes on source, boundary center, list of nodes on target, target center
     821                 :            : // output: 3x3 matrix A such that
     822                 :            : //  target= A * ( source - 2*sc + tc) + sc
     823                 :         32 : void OneToOneSwept::computeTransformationFromSourceToTarget(std::vector<Vector3D> & sNodes, Vector3D & sc,
     824                 :            :       std::vector<Vector3D> & tNodes, Vector3D & tc, Matrix3D & transMatrix)
     825                 :            : {
     826         [ +  - ]:         32 :   Matrix3D tmpMatrix(0.0);
     827         [ +  - ]:         32 :   Matrix3D bMatrix(0.0);
     828                 :            :   //transform the coordinates
     829                 :         32 :   int size = (int)sNodes.size();
     830         [ -  + ]:         32 :   assert(sNodes.size() == tNodes.size());
     831         [ +  + ]:       2086 :   for (int i = 0; i < size; i++)
     832                 :            :   {
     833                 :            :     //transform the boundary nodes
     834 [ +  - ][ +  - ]:       2054 :     sNodes[i] = sNodes[i] - 2 * sc + tc;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     835 [ +  - ][ +  - ]:       2054 :     tNodes[i] = tNodes[i] - sc;
         [ +  - ][ +  - ]
     836                 :            :   }
     837                 :            : 
     838                 :            :   //calculate the transformation matrix: transform the nodes on the source surface to the target surface in the physical space
     839         [ +  + ]:       2086 :   for (int i = 0; i < size; i++)
     840                 :            :   {
     841 [ +  - ][ +  - ]:       2054 :     tmpMatrix = tmpMatrix + sNodes[i]*transpose(sNodes[i]);
         [ +  - ][ +  - ]
                 [ +  - ]
     842 [ +  - ][ +  - ]:       2054 :     bMatrix = bMatrix + tNodes[i]*transpose(sNodes[i]);
         [ +  - ][ +  - ]
                 [ +  - ]
     843                 :            :   }
     844                 :            : 
     845                 :            :   //first determine the affine mapping matrix is singular or not
     846         [ +  - ]:         32 :   double detValue = det(tmpMatrix);
     847                 :            :   (void) detValue;
     848 [ +  - ][ -  + ]:         32 :   assert(pow(detValue, 2)>1.0e-20);
     849                 :            : 
     850                 :            :   //solve the affine mapping matrix, make use of inverse matrix to get affine mapping matrix
     851         [ +  - ]:         32 :   Matrix3D InvMatrix = inverse(tmpMatrix);
     852         [ +  - ]:         32 :   transMatrix = bMatrix*InvMatrix;
     853                 :            : 
     854                 :         32 : }
     855                 :            : // use similar code to TargetSurfProjection, but do not project on surface...
     856                 :          6 : int OneToOneSwept::ProjectInteriorLayers(std::vector<moab::EntityHandle> & boundLayers, vector<vector<Vertex> > & linkVertexList)
     857                 :            : {
     858                 :            :   iMesh::Error m_err;
     859 [ +  - ][ +  - ]:          6 :   Vector3D sPtsCenter(0.), tPtsCenter(0.);
     860         [ +  - ]:          6 :   std::vector<Vector3D> PtsCenter(numLayers - 1);
     861 [ +  - ][ +  - ]:         12 :   std::vector<Vector3D> sBoundaryNodes(0), tBoundaryNodes(0);
     862                 :            : 
     863                 :          6 :   iBase_TagHandle taghandle = 0;
     864 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->getTagHandle("source", taghandle);
                 [ +  - ]
     865         [ +  - ]:          6 :   IBERRCHK(m_err, "Trouble getting the source tag handle");
     866                 :            : 
     867         [ +  - ]:         12 :   std::vector<Vector3D> latCoords;
     868         [ +  - ]:          6 :   latCoords.resize(boundLayers.size() - 2 * sizeBLayer);// to store the coordinates of the lateral points
     869                 :            :   // (exclude the source and target, they are already in NodeList and TVertexList)...
     870                 :            : 
     871 [ +  - ][ +  - ]:          6 :   moab::ErrorCode rval = mb->get_coords(&(boundLayers[sizeBLayer]), latCoords.size(), &(latCoords[0][0])); //these are the nodes for lateral sides
         [ +  - ][ +  - ]
     872 [ -  + ][ #  # ]:          6 :   MBERRCHK(rval, mb);
         [ #  # ][ #  # ]
     873                 :            : 
     874                 :            :   //calculate the center coordinates
     875         [ +  + ]:         19 :   for (int i = 0; i < numLayers - 1; i++)
     876 [ +  - ][ +  - ]:         13 :     PtsCenter[i].set(0.);
     877                 :            : 
     878                 :          6 :   int numPts = sizeBLayer;// a lot of repetition ; do we really need
     879         [ +  - ]:          6 :   sBoundaryNodes.resize(numPts);// another useless copy
     880         [ +  - ]:          6 :   tBoundaryNodes.resize(numPts);// another useless copy
     881         [ +  + ]:        444 :   for (int j = 0; j < sizeBLayer; j++)
     882                 :            :   {
     883         [ +  - ]:        438 :     iBase_EntityHandle sBNode = (iBase_EntityHandle) boundLayers[j];
     884                 :            :     int i;
     885                 :            :     // this is the index in NodeList...
     886 [ +  - ][ +  - ]:        438 :     m_err = mk_core()->imesh_instance()->getIntData(sBNode, taghandle, i);
                 [ +  - ]
     887         [ +  - ]:        438 :     IBERRCHK(m_err, "Trouble get the int value for nodes in the mesh instance.");
     888                 :            : 
     889 [ +  - ][ +  - ]:        438 :     sPtsCenter += NodeList[i].xyz;
     890 [ +  - ][ +  - ]:        438 :     tPtsCenter += TVertexList[i].xyz;
     891                 :            : 
     892 [ +  - ][ +  - ]:        438 :     sBoundaryNodes[j] = NodeList[i].xyz;
     893 [ +  - ][ +  - ]:        438 :     tBoundaryNodes[j] = TVertexList[i].xyz;
     894                 :            : 
     895         [ +  + ]:       1246 :     for (int lay = 0; lay < numLayers - 1; lay++)
     896                 :            :     {
     897                 :            :       // interior layers
     898                 :        808 :       int indexNodeOnSide = lay * sizeBLayer + j;// all p3d will be above index i
     899         [ +  - ]:        808 :       Vector3D & p3d = latCoords[indexNodeOnSide];
     900 [ +  - ][ +  - ]:        808 :       PtsCenter[lay] += p3d;
     901 [ +  - ][ +  - ]:        808 :       linkVertexList[lay][i].xyz = p3d;
     902 [ +  - ][ +  - ]:        808 :       linkVertexList[lay][i].gVertexHandle = (iBase_EntityHandle) boundLayers[indexNodeOnSide + sizeBLayer];
                 [ +  - ]
     903                 :            :     }
     904                 :            :   }
     905                 :            : 
     906 [ +  - ][ +  - ]:          6 :   sPtsCenter = sPtsCenter / numPts;
     907 [ +  - ][ +  - ]:          6 :   tPtsCenter = tPtsCenter / numPts;
     908                 :            : 
     909                 :            :   //calculate the center coordinates for the ith layer
     910         [ +  + ]:         19 :   for (int i = 0; i < numLayers - 1; i++)
     911 [ +  - ][ +  - ]:         13 :     PtsCenter[i] = PtsCenter[i] / numPts;
         [ +  - ][ +  - ]
     912                 :            : 
     913         [ +  - ]:         12 :   std::vector<Vector3D> sNodes(numPts); //boundary nodes on the source surface
     914         [ +  - ]:         12 :   std::vector<Vector3D> tNodes(numPts); //boundary nodes on the target surface
     915 [ +  - ][ +  - ]:         12 :   std::vector<Vector3D> isBNodes(numPts), itBNodes(numPts); //boundary nodes on the different layers
     916                 :            : 
     917                 :            :   //loop over different layers
     918         [ +  + ]:         19 :   for (int i = 0; i < numLayers - 1; i++)
     919                 :            :   {
     920         [ +  + ]:        821 :     for (int j = 0; j < numPts; j++)
     921                 :            :     {
     922 [ +  - ][ +  - ]:        808 :       sNodes[j] = sBoundaryNodes[j];
     923 [ +  - ][ +  - ]:        808 :       tNodes[j] = tBoundaryNodes[j];
     924                 :            :       //coordinates on the different layers
     925 [ +  - ][ +  - ]:        808 :       isBNodes[j] = itBNodes[j] = latCoords[i*sizeBLayer + j];
                 [ +  - ]
     926                 :            :     }
     927                 :            : 
     928 [ +  - ][ +  - ]:         13 :     Matrix3D sA, tA;
     929                 :            :     // from source to layer i
     930 [ +  - ][ +  - ]:         13 :     computeTransformationFromSourceToTarget(sNodes, sPtsCenter, isBNodes, PtsCenter[i], sA);
     931                 :            :     // from target to layer i
     932 [ +  - ][ +  - ]:         13 :     computeTransformationFromSourceToTarget(tNodes, tPtsCenter, itBNodes, PtsCenter[i], tA);
     933                 :            :     //calculate the inner nodes for different layers
     934                 :         13 :     double s = (i + 1) / double(numLayers); // interpolation factor
     935         [ +  + ]:       2258 :     for (unsigned int j = 0; j < NodeList.size(); j++)
     936                 :            :     {
     937 [ +  - ][ +  + ]:       2245 :       if (!(NodeList[j].onBoundary))
     938                 :            :       {
     939 [ +  - ][ +  - ]:       1437 :         Vector3D spts, tpts, pts;
                 [ +  - ]
     940                 :            :         iBase_EntityHandle nodeHandle;
     941 [ +  - ][ +  - ]:       1437 :         spts = sA * (NodeList[j].xyz - 2 * sPtsCenter + PtsCenter[i])+sPtsCenter;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     942 [ +  - ][ +  - ]:       1437 :         tpts = tA * (TVertexList[j].xyz - 2 * tPtsCenter + PtsCenter[i])+tPtsCenter;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     943                 :            :         // interpolate the 2 results
     944 [ +  - ][ +  - ]:       1437 :         pts = (1-s) * spts + s * tpts;
         [ +  - ][ +  - ]
     945                 :            : 
     946 [ +  - ][ +  - ]:       1437 :         linkVertexList[i][j].xyz = pts;
     947                 :            : 
     948 [ +  - ][ +  - ]:       1437 :         m_err = mk_core()->imesh_instance()->createVtx(pts[0], pts[1], pts[2], nodeHandle);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     949         [ +  - ]:       1437 :         IBERRCHK(m_err, "Trouble create the vertex entity.");
     950 [ +  - ][ +  - ]:       1437 :         linkVertexList[i][j].gVertexHandle = nodeHandle;
     951 [ +  - ][ +  - ]:       1437 :         m_err = mk_core()->imesh_instance()->addEntToSet(nodeHandle, volumeSet);
                 [ +  - ]
     952         [ +  - ]:       1437 :         IBERRCHK(m_err, "Trouble add the node handle to the entity set.");
     953                 :            :       }
     954                 :            :     }
     955                 :            :   }
     956                 :          6 :   return 1;
     957                 :            : }
     958                 :            : 
     959                 :            : //****************************************************************************//
     960                 :            : // function   : CreateElements
     961                 :            : // Author     : Shengyong Cai
     962                 :            : // Date       : Feb 16, 2011
     963                 :            : // Description: create hexahedral elements by connecting 8 nodes which have
     964                 :            : //              already been created by previous functions
     965                 :            : //***************************************************************************//
     966                 :          6 : int OneToOneSwept::CreateElements(vector<vector<Vertex> > &linkVertexList)
     967                 :            : {
     968                 :            :   //create the quadrilateral elements on the different layers
     969                 :            :   //it is not necessary to create the quadrilateral elements on the different layers. Hex element can be created based on the eight nodes
     970                 :            :   iMesh::Error m_err;
     971         [ +  - ]:          6 :   vector<iBase_EntityHandle> mVolumeHandle(FaceList.size());
     972                 :            :   // first decide orientation, based on the FaceList orientation, and first node above
     973                 :            :   // take one face on source, and first node above in layer 1
     974 [ +  - ][ +  - ]:          6 :   Vertex * v1 = FaceList[0].connect[0];
     975 [ +  - ][ +  - ]:          6 :   Vertex * v2 = FaceList[0].connect[1];
     976 [ +  - ][ +  - ]:          6 :   Vertex * v3 = FaceList[0].connect[2];
     977                 :            :   // vertex 4 is on layer 1, above vertex 1
     978                 :          6 :   int ind1 = v1->index;
     979                 :            :   Vertex * v4;
     980         [ +  - ]:          6 :   if (numLayers > 1)
     981 [ +  - ][ +  - ]:          6 :     v4 = &linkVertexList[0][ind1];
     982                 :            :   else
     983         [ #  # ]:          0 :     v4 = &TVertexList[ind1];
     984                 :            : 
     985 [ +  - ][ +  - ]:          6 :   Vector3D normal1 = (v2->xyz-v1->xyz)*(v3->xyz-v1->xyz);
         [ +  - ][ +  - ]
     986 [ +  - ][ +  - ]:          6 :   double vol6= normal1 % (v4->xyz-v1->xyz);
     987         [ +  - ]:          6 :   std::cout << "Orientation is ";
     988                 :          6 :   int skip = 0;
     989         [ +  + ]:          6 :   if (vol6 < 0)
     990                 :            :   {
     991         [ +  - ]:          5 :     std::cout <<"negative\n";
     992                 :          5 :     skip=4;
     993                 :            :   }
     994                 :            :   else
     995         [ +  - ]:          1 :     std::cout <<"positive\n";
     996                 :            : 
     997         [ +  - ]:         12 :   vector<iBase_EntityHandle> connect(8);
     998         [ +  + ]:         25 :   for (int m = 0; m < numLayers; m++)
     999                 :            :   {
    1000         [ +  + ]:       2795 :     for (unsigned int i = 0; i < FaceList.size(); i++)
    1001                 :            :     {
    1002         [ +  + ]:      13880 :       for (int k = 0; k < 4; k++)
    1003                 :            :       {
    1004         [ +  + ]:      11104 :         if (m == 0) // the first layer is the source layer
    1005         [ +  - ]:       3780 :           connect[k + skip] = NodeList
    1006 [ +  - ][ +  - ]:       3780 :               [(FaceList[i].connect[k])->index].gVertexHandle;
                 [ +  - ]
    1007                 :            :         else // the first layer is an intermediate layer
    1008 [ +  - ][ +  - ]:      14648 :           connect[k + skip] = linkVertexList[m - 1]
    1009 [ +  - ][ +  - ]:      14648 :               [(FaceList[i].connect[k])->index].gVertexHandle;
                 [ +  - ]
    1010         [ +  + ]:      11104 :         if (m == (numLayers - 1)) // the second layer is the target layer
    1011         [ +  - ]:       3780 :           connect[(k + skip + 4) % 8] = TVertexList
    1012 [ +  - ][ +  - ]:       3780 :               [(FaceList[i].connect[k])->index].gVertexHandle;
                 [ +  - ]
    1013                 :            :         else // the second layer is an intermediate layer
    1014 [ +  - ][ +  - ]:      14648 :           connect[(k + skip + 4) % 8] = linkVertexList[m]
    1015 [ +  - ][ +  - ]:      14648 :               [(FaceList[i].connect[k])->index].gVertexHandle;
                 [ +  - ]
    1016                 :            :       }
    1017                 :            :       m_err = mk_core()->imesh_instance()->createEnt(iMesh_HEXAHEDRON,
    1018 [ +  - ][ +  - ]:       2776 :           &connect[0], 8, mVolumeHandle[i]);
         [ +  - ][ +  - ]
                 [ +  - ]
    1019         [ +  - ]:       2776 :       IBERRCHK(m_err, "Trouble creating the hexahedral element.");
    1020                 :            :     }
    1021 [ +  - ][ +  - ]:         19 :     m_err = mk_core()->imesh_instance()->addEntArrToSet(&mVolumeHandle[0],
                 [ +  - ]
    1022         [ +  - ]:         38 :         FaceList.size(), volumeSet);
    1023                 :         19 :     IBERRCHK(m_err,
    1024         [ +  - ]:         19 :         "Trouble adding an array of hexahedral elements to the entity set.");
    1025                 :            :   }
    1026                 :          6 :   return 1;
    1027                 :            : }
    1028                 :            : 
    1029                 :            : #ifdef HAVE_MESQUITE
    1030                 :            : //target surface mesh smoothing by Mesquite
    1031                 :          6 : void OneToOneSwept::SurfMeshOptimization()
    1032                 :            : {
    1033                 :          6 :   MEntSelection::iterator mit = mentSelection.begin();
    1034         [ +  - ]:          6 :   ModelEnt *me = mit -> first;
    1035         [ +  - ]:          6 :   int irelPairIndex = me->iRelPairIndex();
    1036 [ +  - ][ +  - ]:          6 :   iGeom * igeom_inst = mk_core()->igeom_instance(me->iGeomIndex());
                 [ +  - ]
    1037                 :            :   //create a tag to attach the coordinates to nodes
    1038                 :          6 :   iBase_TagHandle mapped_tag = 0;
    1039 [ +  - ][ +  - ]:          6 :   iMesh::Error m_err = mk_core()->imesh_instance()->getTagHandle("MsqAltCoords", mapped_tag);
                 [ +  - ]
    1040         [ +  - ]:          6 :   if (m_err)
    1041                 :            :   {
    1042 [ +  - ][ +  - ]:          6 :     m_err = mk_core()->imesh_instance()->createTag("MsqAltCoords", 3, iBase_DOUBLE, mapped_tag);
                 [ +  - ]
    1043         [ +  - ]:          6 :     IBERRCHK(m_err, "Trouble create a tag.");
    1044                 :            : 
    1045                 :            :   }
    1046                 :            :   //attach the coordinates to the nodes
    1047                 :          6 :   double tag_data[3*TVertexList.size()];
    1048         [ +  - ]:          6 :   std::vector<iBase_EntityHandle> vertexHandle(TVertexList.size());
    1049         [ +  + ]:       1173 :   for (unsigned int i = 0; i < NodeList.size();i++)
    1050                 :            :   {
    1051 [ +  - ][ +  - ]:       1167 :     tag_data[3*i] = NodeList[i].xyz[0];
    1052 [ +  - ][ +  - ]:       1167 :     tag_data[3*i+1] = NodeList[i].xyz[1];
    1053 [ +  - ][ +  - ]:       1167 :     tag_data[3*i+2] = NodeList[i].xyz[2];
    1054 [ +  - ][ +  - ]:       1167 :     vertexHandle[i] = TVertexList[i].gVertexHandle;
    1055                 :            :   }
    1056 [ +  - ][ +  - ]:          6 :   m_err = mk_core()->imesh_instance()->setDblArrData(&vertexHandle[0], NodeList.size(), mapped_tag, &tag_data[0]);
         [ +  - ][ +  - ]
    1057         [ +  - ]:          6 :   IBERRCHK(m_err, "Trouble set an array of int data to nodes.");
    1058                 :            : 
    1059                 :            :   //get the mesh entityset for target surface
    1060                 :            :   iBase_EntitySetHandle surfSets;
    1061 [ +  - ][ +  - ]:          6 :   iRel::Error r_err = mk_core()->irel_pair(irelPairIndex)->getEntSetRelation(targetSurface, 0, surfSets);
                 [ +  - ]
    1062         [ +  - ]:          6 :   IBERRCHK(r_err, "Trouble get the mesh entity set for the target surface.");
    1063                 :            :   //call the MeshImprove class to smooth the target surface mesh by using Mesquite
    1064 [ +  - ][ +  - ]:         12 :   MeshImprove meshopt(mk_core(), false, true, true, true, igeom_inst);
    1065         [ +  - ]:         12 :   meshopt.SurfMeshImprove(targetSurface, surfSets, iBase_FACE);
    1066                 :          6 : }
    1067                 :            : #endif
    1068 [ +  - ][ +  - ]:        156 : }
    1069                 :            : 

Generated by: LCOV version 1.11