LCOV - code coverage report
Current view: top level - algs - ExtrudeMesh.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 139 150 92.7 %
Date: 2020-07-01 15:24:36 Functions: 12 13 92.3 %
Branches: 196 392 50.0 %

           Branch data     Line data    Source code
       1                 :            : #include "meshkit/ExtrudeMesh.hpp"
       2                 :            : #include "meshkit/CopyMesh.hpp"
       3                 :            : #include "meshkit/MKCore.hpp"
       4                 :            : #include "meshkit/ModelEnt.hpp"
       5                 :            : #include "meshkit/SizingFunction.hpp"
       6                 :            : #include "meshkit/RegisterMeshOp.hpp"
       7                 :            : #include "meshkit/LocalSet.hpp"
       8                 :            : 
       9                 :            : #include "iMesh_extensions.h"
      10                 :            : 
      11                 :            : #define CHKERR(err) do {                        \
      12                 :            :   if ((err) != iBase_SUCCESS)                   \
      13                 :            :     return iBase_ErrorType(err);                \
      14                 :            :   } while(false)
      15                 :            : 
      16                 :            : namespace MeshKit
      17                 :            : {
      18                 :            : 
      19                 :            :   // static registration of this  mesh scheme
      20                 :            :   moab::EntityType ExtrudeMesh_tps[] = { moab::MBVERTEX,
      21                 :            :                                          moab::MBEDGE,
      22                 :            :                                          moab::MBTRI,
      23                 :            :                                          moab::MBHEX,
      24                 :            :                                          moab::MBMAXTYPE};
      25                 :            : 
      26                 :         40 :   const moab::EntityType* ExtrudeMesh::output_types()
      27                 :         40 :     { return ExtrudeMesh_tps; }
      28                 :            : 
      29                 :          3 :   ExtrudeMesh::ExtrudeMesh(MKCore *mkcore, const MEntVector &me_vec)
      30                 :            :     : MeshScheme(mkcore, me_vec),
      31         [ +  - ]:          3 :       mesh(mkcore->imesh_instance()),
      32                 :            :       extrudeTag(mkcore, "__ExtrudeMeshTag"),
      33                 :            :       copyTag(mkcore, "__CopyMeshTag"),
      34                 :            :       transform(0),
      35                 :            :       copyFaces(false),
      36                 :            :       extrudeSets(mkcore),
      37                 :            :       copySets(mkcore),
      38 [ +  - ][ +  - ]:          6 :       expandSets(mkcore)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      39                 :          3 :   {}
      40                 :            : 
      41                 :          9 :   ExtrudeMesh::~ExtrudeMesh()
      42         [ -  + ]:          6 :   {}
      43                 :            : 
      44                 :            : 
      45                 :          0 :   bool ExtrudeMesh::add_modelent(ModelEnt *model_ent)
      46                 :            :   {
      47                 :          0 :     return MeshOp::add_modelent(model_ent);
      48                 :            :   }
      49                 :            : 
      50                 :          3 :   void ExtrudeMesh::setup_this()
      51                 :          3 :   {}
      52                 :            : 
      53                 :          3 :   void ExtrudeMesh::execute_this()
      54                 :            :   {
      55         [ +  - ]:          3 :     std::vector<iMesh::EntityHandle> orig_ents(mentSelection.size());
      56                 :            : 
      57                 :          3 :     int i = 0;
      58   [ +  -  +  - ]:         14 :     for (MEntSelection::iterator mit = mentSelection.begin();
                 [ +  + ]
      59                 :          7 :          mit != mentSelection.end(); mit++) {
      60         [ +  - ]:          4 :       ModelEnt *me = mit->first;
      61 [ +  - ][ +  - ]:          4 :       orig_ents[i++] = reinterpret_cast<iBase_EntityHandle> (me->mesh_handle());
      62                 :            :     }
      63                 :            : 
      64 [ +  - ][ +  - ]:          6 :     LocalSet set(this->mk_core());
      65                 :            : 
      66 [ +  - ][ +  - ]:          3 :     IBERRCHK(mesh->addEntArrToSet(&orig_ents[0], orig_ents.size(), set), *mesh);
         [ +  - ][ +  - ]
      67 [ +  - ][ +  - ]:          6 :     do_extrude(set);
      68                 :          3 :   }
      69                 :            : 
      70                 :          3 :   int ExtrudeMesh::getStructure(iMesh_Instance instance,
      71                 :            :                              iBase_EntitySetHandle set,
      72                 :            :                              std::vector<iBase_EntityHandle> &ents,
      73                 :            :                              std::vector<iBase_EntityHandle> &unique_adj,
      74                 :            :                              std::vector<int> &indices,
      75                 :            :                              std::vector<int> &offsets)
      76                 :            :   {
      77                 :            :       // 1) Get source entities, making sure verts are first
      78                 :            :       int num;
      79                 :            :       int err;
      80         [ +  - ]:          3 :       iMesh_getNumOfTypeRec(instance, set, iBase_ALL_TYPES, true, &num, &err);
      81         [ -  + ]:          3 :       CHKERR(err);
      82                 :            : 
      83         [ +  - ]:          3 :       ents.resize(num);
      84         [ +  - ]:          3 :       offsets.resize(num+1);
      85                 :            : 
      86         [ +  - ]:          3 :       iBase_EntityHandle *block = &ents[0];
      87                 :          3 :       int block_alloc = ents.size(), block_size, num_verts = 0;
      88 [ +  - ][ +  + ]:         17 :       for (int t = iMesh_POINT; t < iMesh_ALL_TOPOLOGIES && block_alloc; ++t) {
      89                 :            :           iMesh_getEntitiesRec(instance, set, iBase_ALL_TYPES, t, true,
      90         [ +  - ]:         14 :                                &block, &block_alloc, &block_size, &err);
      91         [ -  + ]:         14 :           CHKERR(err);
      92                 :            : 
      93                 :         14 :           block_alloc -= block_size;
      94                 :         14 :           block += block_size;
      95         [ +  + ]:         14 :           if (t == iMesh_POINT)
      96                 :          3 :               num_verts = block_size;
      97                 :            :       }
      98                 :            : 
      99                 :            :       // 2) Get verts adjacent to all source entitites (verts are adj to themselves)
     100 [ +  - ][ +  - ]:          3 :       std::vector<iBase_EntityHandle> all_adj(ents.begin(), ents.begin()+num_verts);
     101                 :            : 
     102                 :            :       // first, fill the vertex-vertex adjacencies
     103         [ -  + ]:          3 :       for (int i = 0; i < num_verts; ++i)
     104         [ #  # ]:          0 :           offsets[i] = i;
     105                 :            : 
     106                 :          3 :       iBase_EntityHandle *tmp_adj = NULL;
     107                 :          3 :       int tmp_adj_alloc = 0, tmp_adj_size;
     108         [ +  - ]:          3 :       int *tmp_off = &offsets[num_verts];
     109                 :          3 :       int tmp_off_alloc = offsets.size() - num_verts, tmp_off_size;
     110         [ +  - ]:          3 :       iMesh_getEntArrAdj(instance, &ents[num_verts], ents.size()-num_verts,
     111                 :            :                          iBase_VERTEX, &tmp_adj, &tmp_adj_alloc, &tmp_adj_size,
     112         [ +  - ]:          3 :                          &tmp_off, &tmp_off_alloc, &tmp_off_size, &err);
     113         [ -  + ]:          3 :       CHKERR(err);
     114                 :            : 
     115                 :            :       // shift all the offsets to account for vertices
     116         [ +  + ]:         10 :       for(unsigned int i = num_verts; i < offsets.size(); ++i)
     117         [ +  - ]:          7 :           offsets[i] += num_verts;
     118                 :            : 
     119         [ +  - ]:          3 :       all_adj.reserve(all_adj.size() + tmp_adj_size);
     120         [ +  - ]:          3 :       all_adj.insert(all_adj.end(), tmp_adj, tmp_adj+tmp_adj_size);
     121                 :          3 :       free(tmp_adj);
     122                 :            : 
     123                 :            :       // 3) Get unique adjacent vertices and offsets
     124         [ +  - ]:          3 :       unique_adj.resize(all_adj.size());
     125         [ +  - ]:          3 :       indices.resize(all_adj.size());
     126         [ +  - ]:          3 :       std::copy(all_adj.begin(), all_adj.end(), unique_adj.begin());
     127         [ +  - ]:          3 :       std::sort(unique_adj.begin(), unique_adj.end());
     128                 :            : 
     129                 :            :       size_t unique_size;
     130 [ +  - ][ +  - ]:          3 :       unique_size = std::unique(unique_adj.begin(), unique_adj.end()) -
     131                 :          3 :               unique_adj.begin();
     132         [ +  - ]:          3 :       unique_adj.resize(unique_size);
     133                 :            : 
     134         [ +  + ]:         18 :       for (size_t i = 0; i < all_adj.size(); ++i) {
     135         [ +  - ]:         15 :           indices[i] = std::lower_bound(unique_adj.begin(), unique_adj.end(),
     136 [ +  - ][ +  - ]:         15 :                                         all_adj[i]) - unique_adj.begin();
                 [ +  - ]
     137                 :            :       }
     138                 :            : 
     139                 :          3 :       return 0;
     140                 :            :   }
     141                 :            : 
     142                 :          3 :   void ExtrudeMesh::update_sets()
     143                 :            :   {
     144                 :          3 :     copySets.update_tagged_sets();
     145                 :          3 :     expandSets.update_tagged_sets();
     146                 :          3 :   }
     147                 :            : 
     148                 :          3 :   void ExtrudeMesh::do_extrude(iBase_EntitySetHandle src)
     149                 :            :   {
     150 [ +  - ][ +  - ]:          3 :     assert(transform && transform->steps() > 0);
                 [ -  + ]
     151                 :            : 
     152         [ +  - ]:          3 :     update_sets();
     153                 :            : 
     154         [ +  - ]:          3 :     std::vector<iBase_EntityHandle> ents;
     155 [ +  - ][ +  - ]:          6 :     std::vector<iBase_EntityHandle> verts;
     156 [ +  - ][ +  - ]:          6 :     std::vector<int> indices;
     157 [ +  - ][ +  - ]:          6 :     std::vector<int> offsets;
     158                 :            : 
     159                 :            : //    IBERRCHK(iMesh_getStructure(mesh->instance(), src, ents, verts,
     160                 :            : //                                indices, offsets), *mesh);
     161                 :            :     getStructure(mesh->instance(), src, ents, verts,
     162 [ +  - ][ +  - ]:          3 :                                     indices, offsets);
     163                 :            : 
     164         [ -  + ]:          6 :     if (ents.size() == 0) return;
     165                 :            : 
     166 [ +  - ][ +  - ]:          6 :     std::vector<iBase_EntityHandle> curr;
     167         [ +  - ]:          6 :     std::vector<iBase_EntityHandle> next;
     168         [ +  - ]:          6 :     std::vector<int> normals;
     169                 :            : 
     170 [ +  - ][ +  - ]:          6 :     LocalTag local_extrude_tag(this->mk_core());
     171 [ +  - ][ +  - ]:          6 :     LocalTag local_copy_tag(this->mk_core());
     172                 :            : 
     173         [ +  - ]:          3 :     curr.resize(verts.size());
     174         [ +  - ]:          3 :     next.resize(verts.size());
     175         [ +  - ]:          3 :     transform->transform(1, mesh, verts, next);
     176                 :            : 
     177                 :            :     // Get the offset between vertices between steps
     178 [ +  - ][ +  - ]:          3 :     Vector<3> xa, xb, dx;
                 [ +  - ]
     179 [ +  - ][ +  - ]:          3 :     IBERRCHK(mesh->getVtxCoord(next[0],  xa[0], xa[1], xa[2]), *mesh);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     180 [ +  - ][ +  - ]:          3 :     IBERRCHK(mesh->getVtxCoord(verts[0], xb[0], xb[1], xb[2]), *mesh);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     181 [ +  - ][ +  - ]:          3 :     dx = xa-xb;
     182                 :            : 
     183         [ +  - ]:          3 :     get_normals(verts, indices, offsets, dx, normals);
     184                 :            : 
     185                 :            :     // Make the first set of volumes
     186 [ +  - ][ +  - ]:          6 :     connect_up_dots(&ents[0], ents.size(), local_extrude_tag, &normals[0],
     187 [ +  - ][ +  - ]:          9 :                     &indices[0], &offsets[0], &verts[0], &next[0]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     188                 :            : 
     189                 :            :     // Now do the rest
     190 [ +  - ][ +  + ]:         21 :     for (int i=2; i<=transform->steps(); i++) {
     191         [ +  - ]:         18 :       std::swap(curr, next);
     192         [ +  - ]:         18 :       transform->transform(i, mesh, verts, next);
     193 [ +  - ][ +  - ]:         36 :       connect_up_dots(&ents[0], ents.size(), local_extrude_tag, &normals[0],
     194 [ +  - ][ +  - ]:         54 :                       &indices[0], &offsets[0], &curr[0], &next[0]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     195                 :            :     }
     196                 :            : 
     197 [ +  - ][ +  - ]:          3 :     tag_copy_sets(extrudeSets, local_extrude_tag, extrudeTag);
                 [ +  - ]
     198                 :            : 
     199         [ +  - ]:          3 :     if (copyFaces) {
     200                 :            :       // set the local copy tags on vertices
     201                 :            :       // XXX: Should this really happen? Doing so adds more entities to copysets
     202                 :            :       // than explicitly passed into this function. This may be a domain-
     203                 :            :       // specific question.
     204 [ +  - ][ +  - ]:          3 :       IBERRCHK(mesh->setEHArrData(&verts[0], verts.size(), local_copy_tag,
         [ +  - ][ +  - ]
     205         [ +  - ]:          3 :                                   &next[0]), *mesh);
     206                 :            : 
     207 [ +  - ][ +  - ]:          3 :       connect_the_dots(mesh, local_copy_tag, ents, indices, offsets, next);
     208                 :            : 
     209 [ +  - ][ +  - ]:          3 :       link_expand_sets(expandSets, local_copy_tag);
     210                 :            : 
     211 [ +  - ][ +  - ]:          3 :       process_ce_sets(mesh, copySets.sets(), local_copy_tag);
                 [ +  - ]
     212 [ +  - ][ +  - ]:          3 :       process_ce_sets(mesh, expandSets.sets(), local_copy_tag);
                 [ +  - ]
     213                 :            : 
     214 [ +  - ][ +  - ]:          3 :       tag_copy_sets(copySets, local_copy_tag, copyTag);
                 [ +  - ]
     215                 :          3 :     }
     216                 :            :   }
     217                 :            : 
     218                 :            :   // calculate the normals for each face (1 = towards v, -1 = away from v)
     219                 :            :   // TODO: this can fail with non-convex faces
     220                 :          3 :   void ExtrudeMesh::get_normals(const std::vector<iBase_EntityHandle> &verts,
     221                 :            :                                 const std::vector<int> &indices,
     222                 :            :                                 const std::vector<int> &offsets,
     223                 :            :                                 const Vector<3> &dv, std::vector<int> &normals)
     224                 :            :   {
     225                 :          3 :     size_t size = offsets.size() - 1;
     226                 :          3 :     normals.resize(size);
     227                 :            : 
     228         [ +  + ]:          7 :     for(size_t i=0; i<size; i++) {
     229 [ +  - ][ +  - ]:          4 :       Vector<3> a, b;
     230                 :            :       iBase_EntityHandle curr_verts[3];
     231                 :            : 
     232 [ +  - ][ +  - ]:          4 :       if(offsets[i+1] - offsets[i] > 2) { // face
                 [ +  - ]
     233         [ +  + ]:         16 :         for(int j=0; j<3; j++)
     234 [ +  - ][ +  - ]:         12 :           curr_verts[j] = verts[indices[ offsets[i]+j ]];
                 [ +  - ]
     235                 :            : 
     236         [ +  - ]:          4 :         std::vector< Vector<3> > coords(3);
     237 [ +  - ][ +  - ]:          4 :         IBERRCHK(mesh->getVtxArrCoords(curr_verts, 3, iBase_INTERLEAVED,
     238         [ +  - ]:          4 :                                        vec2ptr(coords)), *mesh);
     239                 :            : 
     240 [ +  - ][ +  - ]:          4 :         a = coords[1] - coords[0];
         [ +  - ][ +  - ]
     241 [ +  - ][ +  - ]:          4 :         b = coords[2] - coords[1];
         [ +  - ][ +  - ]
     242 [ +  - ][ +  - ]:          4 :         normals[i] = (vector_product(a, b) % dv) > 0 ? 1:-1;
         [ +  - ][ +  - ]
     243                 :            :       }
     244 [ #  # ][ #  # ]:          0 :       else if(offsets[i+1] - offsets[i] == 2) { // line
                 [ #  # ]
     245         [ #  # ]:          0 :         normals[i] = 1; // TODO: figure out a way of distinguishing swapped
     246                 :            :                         // lines
     247                 :            :       }
     248                 :            :       else // vertex
     249         [ #  # ]:          0 :         normals[i] = 1;
     250                 :            :     }
     251                 :          3 :   }
     252                 :            : 
     253                 :         21 :   void ExtrudeMesh::connect_up_dots(
     254                 :            :     iBase_EntityHandle *src, int size, iBase_TagHandle local_tag,
     255                 :            :     int *pre_norms,  int *pre_inds,  int *pre_offs,  iBase_EntityHandle *pre,
     256                 :            :     int *post_norms, int *post_inds, int *post_offs, iBase_EntityHandle *post)
     257                 :            :   {
     258         [ +  + ]:         43 :     for(int i=0; i<size; i++) {
     259                 :         22 :       int count = pre_offs[i+1] - pre_offs[i];
     260                 :            : 
     261                 :            :       // If the normal is facing in the wrong direction (away from the
     262                 :            :       // translation) we add the vertices in reverse order. Otherwise, we go
     263                 :            :       // in the usual order. If count is 2, then we are creating quads and so
     264                 :            :       // need to swap the order of the post set of verts.
     265                 :            : 
     266                 :         22 :       int dx = pre_norms [i];
     267         [ -  + ]:         22 :       int dy = post_norms[i] * (count == 2 ? -1:1);
     268         [ +  - ]:         22 :       int x  = (dx == 1) ? pre_offs [i] : pre_offs [i+1]-1;
     269         [ +  - ]:         22 :       int y  = (dy == 1) ? post_offs[i] : post_offs[i+1]-1;
     270                 :            : 
     271 [ +  - ][ +  - ]:         22 :       iBase_EntityHandle *nodes = new iBase_EntityHandle[count*2];
     272         [ +  + ]:        100 :       for(int j=0; j<count; j++) {
     273                 :         78 :         nodes[j]       = pre [ pre_inds [x + dx*j] ];
     274                 :         78 :         nodes[j+count] = post[ post_inds[y + dy*j] ];
     275                 :            :       }
     276                 :            : 
     277                 :            :       iBase_EntityHandle out;
     278                 :            : 
     279                 :            :       iMesh::Error err;
     280         [ +  + ]:         22 :       if(count == 4)      // quad
     281         [ +  - ]:         12 :         err = mesh->createEnt(iMesh_HEXAHEDRON, nodes, 8, out);
     282         [ +  - ]:         10 :       else if(count == 3) // tri
     283         [ +  - ]:         10 :         err = mesh->createEnt(iMesh_PRISM, nodes, 6, out);
     284         [ #  # ]:          0 :       else if(count == 2) // line
     285         [ #  # ]:          0 :         err = mesh->createEnt(iMesh_QUADRILATERAL, nodes, 4, out);
     286         [ #  # ]:          0 :       else if(count == 1) // vertex
     287         [ #  # ]:          0 :         err = mesh->createEnt(iMesh_LINE_SEGMENT, nodes, 2, out);
     288                 :            :       else
     289         [ #  # ]:          0 :         throw Error(iBase_FAILURE, "Couldn't extrude face; unusual shape.");
     290                 :            : 
     291         [ +  - ]:         22 :       IBERRCHK(err, *mesh);
     292         [ +  - ]:         22 :       delete[] nodes;
     293                 :            : 
     294 [ +  - ][ +  - ]:         22 :       IBERRCHK(mesh->setEHData(src[i], local_tag, out), *mesh);
     295                 :            :     }
     296                 :            : 
     297                 :         21 :     process_ce_sets(mesh, extrudeSets.sets(), local_tag);
     298                 :         21 :   }
     299 [ +  - ][ +  - ]:        156 : } // namespace MeshKit

Generated by: LCOV version 1.11