LCOV - code coverage report
Current view: top level - algs/AdvFront - AF2DfltTriangleMeshOp.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 106 133 79.7 %
Date: 2020-07-01 15:24:36 Functions: 9 13 69.2 %
Branches: 140 302 46.4 %

           Branch data     Line data    Source code
       1                 :            : #include "meshkit/AF2DfltTriangleMeshOp.hpp"
       2                 :            : 
       3                 :            : // C++
       4                 :            : #include <cstddef>
       5                 :            : #include <list>
       6                 :            : #include <vector>
       7                 :            : 
       8                 :            : // MOAB
       9                 :            : #include "moab/Interface.hpp"
      10                 :            : #include "moab/Range.hpp"
      11                 :            : #include "moab/ReadUtilIface.hpp"
      12                 :            : #include "moab/Types.hpp"
      13                 :            : 
      14                 :            : // MeshKit
      15                 :            : #include "meshkit/AF2Algorithm.hpp"
      16                 :            : #include "meshkit/AF2AlgorithmResult.hpp"
      17                 :            : #include "meshkit/AF2DfltPlaneProjMaker.hpp"
      18                 :            : #include "meshkit/AF2DfltTriangleRules.hpp"
      19                 :            : #include "meshkit/AF2Point3D.hpp"
      20                 :            : #include "meshkit/Error.hpp"
      21                 :            : #include "meshkit/MeshScheme.hpp"
      22                 :            : #include "meshkit/ModelEnt.hpp"
      23                 :            : #include "meshkit/RegisterMeshOp.hpp"
      24                 :            : 
      25                 :            : namespace MeshKit
      26                 :            : {
      27                 :            : 
      28                 :            : moab::EntityType AF2DfltTriangleMeshOp::meshTypes[] =
      29                 :            :     {moab::MBVERTEX, moab::MBTRI, moab::MBMAXTYPE};
      30                 :            : 
      31                 :        160 : bool AF2DfltTriangleMeshOp::can_mesh(iBase_EntityType dimension)
      32                 :            : {
      33                 :        160 :   return dimension == iBase_FACE;
      34                 :            : }
      35                 :            : 
      36                 :          0 : bool AF2DfltTriangleMeshOp::can_mesh(ModelEnt *me)
      37                 :            : {
      38                 :          0 :   return canmesh_face(me);
      39                 :            : }
      40                 :            : 
      41                 :       1056 : const char* AF2DfltTriangleMeshOp::name()
      42                 :            : {
      43                 :       1056 :   return "AF2DfltTriangleMeshOp";
      44                 :            : }
      45                 :            : 
      46                 :         42 : const moab::EntityType* AF2DfltTriangleMeshOp::output_types()
      47                 :            : {
      48                 :         42 :   return meshTypes;
      49                 :            : }
      50                 :            : 
      51                 :          9 : AF2DfltTriangleMeshOp::AF2DfltTriangleMeshOp(
      52                 :            :     MKCore *meshkitCore, const MEntVector &meshEntVec) :
      53                 :          9 :     MeshScheme(meshkitCore, meshEntVec)
      54                 :            : {
      55                 :            :   // don't do anything beyond constructing superclass with correct arguments
      56                 :          9 : }
      57                 :            : 
      58                 :         27 : AF2DfltTriangleMeshOp::~AF2DfltTriangleMeshOp()
      59                 :            : {
      60                 :            :   // don't do anything; superclass destructor will be called
      61         [ -  + ]:         18 : }
      62                 :            : 
      63                 :          0 : AF2DfltTriangleMeshOp::AF2DfltTriangleMeshOp(
      64                 :          0 :     const AF2DfltTriangleMeshOp& toCopy) : MeshScheme(toCopy)
      65                 :            : {
      66                 :            :   // don't do anything beyond constructing superclass with correct arguments
      67                 :          0 : }
      68                 :            : 
      69                 :          0 : AF2DfltTriangleMeshOp& AF2DfltTriangleMeshOp::operator=(
      70                 :            :     const AF2DfltTriangleMeshOp& rhs)
      71                 :            : {
      72         [ #  # ]:          0 :   Error notImpl(MeshKit::MK_NOT_IMPLEMENTED);
      73                 :            :   notImpl.set_string(
      74         [ #  # ]:          0 :       "AF2DfltTriangleMeshOp assignment operator is not supported.");
      75         [ #  # ]:          0 :   throw notImpl;
      76                 :            : }
      77                 :            : 
      78                 :          9 : void AF2DfltTriangleMeshOp::execute_this()
      79                 :            : {
      80         [ +  - ]:          9 :   AF2DfltTriangleRules defaultRules;
      81 [ +  - ][ +  - ]:         18 :   AF2Algorithm algorithm(defaultRules.getRules());
      82                 :            : 
      83         [ +  - ]:          9 :   int debug = get_debug_verbosity(); // will call MeshOp to get the debug verbosity level
      84                 :            : 
      85                 :            :   // if some debug level, dump out the mesh so far
      86         [ -  + ]:          9 :   if (debug>0)
      87                 :            :   {
      88                 :            :     // get the moab instance for convenience
      89 [ #  # ][ #  # ]:          0 :     moab::Interface* moabInstance = mk_core()->moab_instance();
      90         [ #  # ]:          0 :     moabInstance->write_file("meshBeforeAF2.vtk");
      91                 :            :   }
      92   [ +  -  +  - ]:         78 :   for (MEntSelection::iterator selIt = mentSelection.begin();
                 [ +  + ]
      93                 :         39 :       selIt != mentSelection.end(); ++selIt)
      94                 :            :   {
      95                 :            :     // extract the model entity from the map iterator
      96         [ +  - ]:         30 :     ModelEnt* modelEnt = selIt->first;
      97                 :            : 
      98 [ +  - ][ -  + ]:         30 :     if (modelEnt->get_meshed_state() >= COMPLETE_MESH)
      99                 :            :     {
     100                 :          0 :       continue;
     101                 :            :     }
     102                 :            : 
     103                 :            :     // get the moab instance for convenience
     104 [ +  - ][ +  - ]:         30 :     moab::Interface* moabInstance = mk_core()->moab_instance();
     105                 :            : 
     106                 :            :     // query the boundary to find mesh edges
     107                 :            :     // Note: the senses returned by this method should be either FORWARD
     108                 :            :     //   or REVERSE, not BOTH . . .
     109                 :            :     //   but I think there is a chance that mesh edges that are on a
     110                 :            :     //   geometric edge that has a sense of BOTH might not agree with
     111                 :            :     //   nearby edges and thus might not form a wire when placed end
     112                 :            :     //   to end.  The AF2Algorithm doesn't require that the input be in
     113                 :            :     //   wire order, and should be okay as long as the edge actually
     114                 :            :     //   does appear with both senses.
     115         [ +  - ]:         30 :     std::vector<moab::EntityHandle> bndryEdges;
     116         [ +  - ]:         60 :     std::vector<int> bEdgeSenses;
     117         [ +  - ]:         30 :     modelEnt->boundary(1, bndryEdges, &bEdgeSenses);
     118                 :            : 
     119                 :            :     // get lists of the vertex coordinates and handles
     120                 :            :     // along with an index from the edge handles into those lists
     121         [ +  - ]:         60 :     std::vector<int> bndryIds;
     122         [ +  - ]:         60 :     std::vector<double> coords;
     123         [ +  - ]:         60 :     moab::Range bndryVertsRange;
     124                 :            :     modelEnt->get_indexed_connect_coords(
     125         [ +  - ]:         30 :         bndryEdges, &bEdgeSenses, NULL, bndryIds, coords, &bndryVertsRange);
     126                 :            :     std::vector<moab::EntityHandle> bndryVertsVec(
     127 [ +  - ][ +  - ]:         60 :         bndryVertsRange.begin(), bndryVertsRange.end());
                 [ +  - ]
     128                 :            : 
     129                 :            :     // convert the edges into the unsigned int format that is needed for
     130                 :            :     // input into the AF2Algorithm
     131                 :            :     // Note: The tags used inside get_indexed_connect_coords are actually
     132                 :            :     // unsigned int (as of May 2016)
     133         [ +  - ]:         60 :     std::vector<unsigned int> inputEdges;
     134         [ +  - ]:       4628 :     for (std::vector<int>::const_iterator bidItr = bndryIds.begin();
           [ +  -  +  - ]
                 [ +  + ]
     135                 :       2314 :         bidItr != bndryIds.end(); ++bidItr)
     136                 :            :     {
     137 [ +  - ][ +  - ]:       2284 :       inputEdges.push_back(*bidItr);
     138                 :            :     }
     139                 :            : 
     140                 :            :     // determine the number of boundary edges and vertices
     141                 :         30 :     unsigned int numVertices = bndryVertsVec.size();
     142                 :         30 :     unsigned int numEdges = inputEdges.size() / 2;
     143                 :            : 
     144                 :            :     // check that there is reasonable data to initialize the front
     145         [ -  + ]:         30 :     if (numEdges <= 0)
     146                 :            :     {
     147         [ #  # ]:          0 :       Error failErr(MeshKit::MK_FAILURE);
     148         [ #  # ]:          0 :       failErr.set_string("There are no boundary mesh edges to use to initialize the advancing front in AF2DfltTriangleMeshOp.");
     149         [ #  # ]:          0 :       throw failErr;
     150                 :            :     }
     151                 :            :     // This should never happen if there are edges, but as a sanity check
     152                 :            :     // since the coordinates of the first vertex may be used to check sizing
     153         [ -  + ]:         30 :     if (numVertices <= 0)
     154                 :            :     {
     155         [ #  # ]:          0 :       Error failErr(MeshKit::MK_FAILURE);
     156                 :            :       failErr.set_string(
     157         [ #  # ]:          0 :           "No boundary vertices found in AF2DfltTriangleMeshOp.");
     158         [ #  # ]:          0 :       throw failErr;
     159                 :            :     }
     160                 :            : 
     161                 :            :     // configure the sizing function, if any, that will be used
     162                 :         30 :     SizingFunction* sizing = NULL;
     163 [ +  - ][ +  + ]:         30 :     if (modelEnt->sizing_function_index() > -1)
     164                 :            :     {
     165         [ +  - ]:         29 :       int sfIndex = modelEnt->sizing_function_index();
     166 [ +  - ][ +  - ]:         29 :       SizingFunction* tempSizing = mk_core()->sizing_function(sfIndex);
     167                 :            :       // check the desired size at the coordinates of the first vertex
     168 [ +  - ][ +  - ]:         29 :       if (tempSizing->size(&coords[0]) > 0)
                 [ +  - ]
     169                 :            :       {
     170                 :         29 :         sizing = tempSizing;
     171                 :            :       }
     172                 :            :     }
     173                 :            : 
     174                 :            :     // construct the local transform maker and run the algorithm
     175                 :            :     AF2DfltPlaneProjMaker localTransformMaker(
     176 [ +  - ][ +  - ]:         60 :         modelEnt->igeom_instance(), modelEnt->geom_handle(), sizing);
                 [ +  - ]
     177                 :            : 
     178                 :            :     AF2AlgorithmResult* meshResult = algorithm.execute(&localTransformMaker,
     179 [ +  - ][ +  - ]:         30 :         &coords[0], numVertices, &inputEdges[0], numEdges, &bndryVertsVec[0], debug);
         [ +  - ][ +  - ]
     180                 :            : 
     181                 :            :     // throw failure if the algorithm did not succeed
     182 [ +  - ][ -  + ]:         30 :     if (!meshResult->isSuccessful())
     183                 :            :     {
     184         [ #  # ]:          0 :       delete meshResult;
     185         [ #  # ]:          0 :       Error failErr(MeshKit::MK_FAILURE);
     186         [ #  # ]:          0 :       failErr.set_string("AF2DfltTriangleMeshOp failed.");
     187         [ #  # ]:          0 :       throw failErr;
     188                 :            :     }
     189                 :            : 
     190                 :            :     // Collect the new points in a vector
     191         [ +  - ]:         30 :     const std::list<AF2Point3D*>* pointList = meshResult->getPoints();
     192         [ +  - ]:         60 :     std::vector<double> newPointCoords;
     193                 :            :     typedef std::list<AF2Point3D*>::const_iterator ConstPointItr;
     194                 :         30 :     int numNewPoints = 0;
     195   [ +  -  +  - ]:      10266 :     for (ConstPointItr pItr = pointList->begin();
                 [ +  + ]
     196                 :       5133 :         pItr != pointList->end(); ++pItr)
     197                 :            :     {
     198 [ +  - ][ +  - ]:       5103 :       if (!(*pItr)->isCommitted())
                 [ +  + ]
     199                 :            :       {
     200                 :       3961 :         ++numNewPoints;
     201 [ +  - ][ +  - ]:       3961 :         newPointCoords.push_back((*pItr)->getX());
                 [ +  - ]
     202 [ +  - ][ +  - ]:       3961 :         newPointCoords.push_back((*pItr)->getY());
                 [ +  - ]
     203 [ +  - ][ +  - ]:       3961 :         newPointCoords.push_back((*pItr)->getZ());
                 [ +  - ]
     204                 :            :       }
     205                 :            :     }
     206                 :            :     // Commit the new points to MOAB
     207         [ +  - ]:         60 :     moab::Range newPointsRange;
     208                 :            :     moabInstance->create_vertices(
     209 [ +  - ][ +  - ]:         30 :         &newPointCoords[0], numNewPoints, newPointsRange);
     210                 :            :     // Set the MOAB handles for the now-committed vertices
     211                 :         30 :     ConstPointItr np3dItr = pointList->begin();
     212 [ +  - ][ +  - ]:       7982 :     for (moab::Range::const_iterator nphItr = newPointsRange.begin();
         [ +  - ][ +  + ]
     213         [ +  - ]:       3991 :         nphItr != newPointsRange.end(); ++nphItr)
     214                 :            :     {
     215 [ +  - ][ +  - ]:       5103 :       while ((*np3dItr)->isCommitted())
                 [ +  + ]
     216                 :            :       {
     217         [ +  - ]:       1142 :         ++np3dItr;
     218                 :            :       }
     219 [ +  - ][ +  - ]:       3961 :       (*np3dItr)->setCommittedHandle(*nphItr);
                 [ +  - ]
     220         [ +  - ]:       3961 :       ++np3dItr;
     221                 :            :     }
     222                 :            : 
     223                 :            :     // get a pointer to the list of new triangles and check how many there are
     224         [ +  - ]:         30 :     const std::list<const AF2Polygon3D*>* faceList = meshResult->getFaces();
     225                 :         30 :     int numTriangles = faceList->size();
     226                 :            : 
     227                 :            :     // pre-allocate connectivity memory to store the triangles
     228                 :            :     moab::ReadUtilIface* readInterface;
     229                 :            :     moab::ErrorCode moabRet;
     230         [ +  - ]:         30 :     moabRet = moabInstance->query_interface(readInterface);
     231 [ -  + ][ #  # ]:         30 :     MBERRCHK(moabRet, moabInstance);
         [ #  # ][ #  # ]
     232                 :            :     moab::EntityHandle firstHandle;
     233                 :            :     moab::EntityHandle* triConnectAry;
     234                 :            :     moabRet = readInterface->get_element_connect(
     235         [ +  - ]:         30 :         numTriangles, 3, moab::MBTRI, 0, firstHandle, triConnectAry);
     236 [ -  + ][ #  # ]:         30 :     MBERRCHK(moabRet, moabInstance);
         [ #  # ][ #  # ]
     237                 :            : 
     238                 :            :     // fill the connectivity array
     239                 :         30 :     unsigned int caIndex = 0u;
     240                 :            :     typedef std::list<const AF2Polygon3D*>::const_iterator ConstTriangleItr;
     241   [ +  -  +  - ]:      18116 :     for (ConstTriangleItr tItr = faceList->begin();
                 [ +  + ]
     242                 :       9058 :         tItr != faceList->end(); ++tItr)
     243                 :            :     {
     244         [ +  + ]:      36112 :       for (unsigned int vi = 0; vi < 3; ++vi)
     245                 :            :       {
     246 [ +  - ][ +  - ]:      27084 :         triConnectAry[caIndex + vi] = (*tItr)->getVertex(vi)->getVertexHandle();
                 [ +  - ]
     247                 :            :       }
     248                 :       9028 :       caIndex += 3;
     249                 :            :     }
     250                 :            : 
     251         [ +  - ]:         30 :     delete meshResult;
     252                 :            : 
     253                 :            :     // Insert the new entities into the entity range
     254 [ +  - ][ +  - ]:         30 :     selIt->second.insert(firstHandle, firstHandle + numTriangles - 1);
     255                 :            : 
     256                 :            :     // Commit the mesh
     257 [ +  - ][ +  - ]:         30 :     modelEnt->commit_mesh(selIt->second, COMPLETE_MESH);
     258                 :         39 :   }
     259                 :          9 : }
     260                 :            : 
     261                 :          0 : const moab::EntityType* AF2DfltTriangleMeshOp::mesh_types_arr() const
     262                 :            : {
     263                 :          0 :   return output_types();
     264                 :            : }
     265                 :            : 
     266                 :          9 : void AF2DfltTriangleMeshOp::setup_this()
     267                 :            : {
     268                 :            :   // Check that the dimension is correct for each model entity and pass
     269                 :            :   // down the sizing functions that are set on the selected surfaces
     270                 :            :   // to their boundary edges if those edges don't have sizing functions set
     271   [ +  -  +  - ]:         78 :   for (MEntSelection::iterator selIt = mentSelection.begin();
                 [ +  + ]
     272                 :         39 :       selIt != mentSelection.end(); ++selIt)
     273                 :            :   {
     274                 :            :     // extract the model entity from the map iterator
     275         [ +  - ]:         30 :     ModelEnt* modelEnt = selIt->first;
     276                 :            : 
     277                 :            :     // check that the dimension of the selected model entity is two
     278 [ +  - ][ -  + ]:         30 :     if (modelEnt->dimension() != 2)
     279                 :            :     {
     280         [ #  # ]:          0 :       Error dimErr(MeshKit::MK_WRONG_DIMENSION);
     281         [ #  # ]:          0 :       dimErr.set_string("Found a selected entity of dimension not equal to 2 in AF2DfltTriangleMeshOp.");
     282         [ #  # ]:          0 :       throw dimErr;
     283                 :            :     }
     284                 :            : 
     285                 :            :     // Try to check whether there is a valid sizing function set on the
     286                 :            :     // model entity.
     287                 :         30 :     int sFIndex = -1;
     288 [ +  - ][ +  + ]:         30 :     if (modelEnt->sizing_function_index() > -1)
     289                 :            :     {
     290         [ +  - ]:         29 :       int tempSFIndex = modelEnt->sizing_function_index();
     291 [ +  - ][ +  - ]:         29 :       SizingFunction* tempSizing = mk_core()->sizing_function(tempSFIndex);
     292                 :            :       // check the desired size at the coordinates of the first vertex
     293 [ +  - ][ +  - ]:         29 :       if (tempSizing->size() > 0)
     294                 :            :       {
     295                 :         29 :         sFIndex = tempSFIndex;
     296                 :            :       }
     297                 :            :     }
     298                 :            : 
     299                 :            :     // If the sizing function appears to be valid, pass it down to adjacent
     300                 :            :     // children that do not have a sizing function set, because it is best
     301                 :            :     // to have the size on the boundaries about right.
     302         [ +  + ]:         30 :     if (sFIndex > -1)
     303                 :            :     {
     304         [ +  - ]:         29 :       MEntVector bndryEdges;
     305         [ +  - ]:         29 :       modelEnt->get_adjacencies(1, bndryEdges);
     306   [ +  -  +  - ]:        358 :       for (MEntVector::iterator beItr = bndryEdges.begin();
                 [ +  + ]
     307                 :        179 :           beItr != bndryEdges.end(); ++beItr)
     308                 :            :       {
     309 [ +  - ][ +  - ]:        150 :         int beSFIndex = (*beItr)->sizing_function_index();
     310         [ +  + ]:        150 :         if (beSFIndex == -1)
     311                 :            :         {
     312 [ +  - ][ +  - ]:          2 :           (*beItr)->sizing_function_index(sFIndex);
     313                 :            :         }
     314                 :         29 :       }
     315                 :            :     }
     316                 :            :   }
     317                 :            : 
     318                 :            :   // Set up the default MeshOp on any children that need one
     319                 :          9 :   setup_boundary();
     320                 :            : 
     321                 :            :   // Make sure that this MeshOp depends on all MeshOps set on its facets
     322                 :          9 :   ensure_facet_dependencies(false);
     323                 :          9 : }
     324                 :            : 
     325 [ +  - ][ +  - ]:        156 : } // namespace MeshKit

Generated by: LCOV version 1.11