MeshKit  1.0
AF2DfltTriangleMeshOp.cpp
Go to the documentation of this file.
00001 #include "meshkit/AF2DfltTriangleMeshOp.hpp"
00002 
00003 // C++
00004 #include <cstddef>
00005 #include <list>
00006 #include <vector>
00007 
00008 // MOAB
00009 #include "moab/Interface.hpp"
00010 #include "moab/Range.hpp"
00011 #include "moab/ReadUtilIface.hpp"
00012 #include "moab/Types.hpp"
00013 
00014 // MeshKit
00015 #include "meshkit/AF2Algorithm.hpp"
00016 #include "meshkit/AF2AlgorithmResult.hpp"
00017 #include "meshkit/AF2DfltPlaneProjMaker.hpp"
00018 #include "meshkit/AF2DfltTriangleRules.hpp"
00019 #include "meshkit/AF2Point3D.hpp"
00020 #include "meshkit/Error.hpp"
00021 #include "meshkit/MeshScheme.hpp"
00022 #include "meshkit/ModelEnt.hpp"
00023 #include "meshkit/RegisterMeshOp.hpp"
00024 
00025 namespace MeshKit
00026 {
00027 
00028 moab::EntityType AF2DfltTriangleMeshOp::meshTypes[] =
00029     {moab::MBVERTEX, moab::MBTRI, moab::MBMAXTYPE};
00030 
00031 bool AF2DfltTriangleMeshOp::can_mesh(iBase_EntityType dimension)
00032 {
00033   return dimension == iBase_FACE;
00034 }
00035 
00036 bool AF2DfltTriangleMeshOp::can_mesh(ModelEnt *me)
00037 {
00038   return canmesh_face(me);
00039 }
00040 
00041 const char* AF2DfltTriangleMeshOp::name()
00042 {
00043   return "AF2DfltTriangleMeshOp";
00044 }
00045 
00046 const moab::EntityType* AF2DfltTriangleMeshOp::output_types()
00047 {
00048   return meshTypes;
00049 }
00050 
00051 AF2DfltTriangleMeshOp::AF2DfltTriangleMeshOp(
00052     MKCore *meshkitCore, const MEntVector &meshEntVec) :
00053     MeshScheme(meshkitCore, meshEntVec)
00054 {
00055   // don't do anything beyond constructing superclass with correct arguments
00056 }
00057 
00058 AF2DfltTriangleMeshOp::~AF2DfltTriangleMeshOp()
00059 {
00060   // don't do anything; superclass destructor will be called
00061 }
00062 
00063 AF2DfltTriangleMeshOp::AF2DfltTriangleMeshOp(
00064     const AF2DfltTriangleMeshOp& toCopy) : MeshScheme(toCopy)
00065 {
00066   // don't do anything beyond constructing superclass with correct arguments
00067 }
00068 
00069 AF2DfltTriangleMeshOp& AF2DfltTriangleMeshOp::operator=(
00070     const AF2DfltTriangleMeshOp& rhs)
00071 {
00072   Error notImpl(MeshKit::MK_NOT_IMPLEMENTED);
00073   notImpl.set_string(
00074       "AF2DfltTriangleMeshOp assignment operator is not supported.");
00075   throw notImpl;
00076 }
00077 
00078 void AF2DfltTriangleMeshOp::execute_this()
00079 {
00080   AF2DfltTriangleRules defaultRules;
00081   AF2Algorithm algorithm(defaultRules.getRules());
00082 
00083   int debug = get_debug_verbosity(); // will call MeshOp to get the debug verbosity level
00084 
00085   // if some debug level, dump out the mesh so far
00086   if (debug>0)
00087   {
00088     // get the moab instance for convenience
00089     moab::Interface* moabInstance = mk_core()->moab_instance();
00090     moabInstance->write_file("meshBeforeAF2.vtk");
00091   }
00092   for (MEntSelection::iterator selIt = mentSelection.begin();
00093       selIt != mentSelection.end(); ++selIt)
00094   {
00095     // extract the model entity from the map iterator
00096     ModelEnt* modelEnt = selIt->first;
00097 
00098     if (modelEnt->get_meshed_state() >= COMPLETE_MESH)
00099     {
00100       continue;
00101     }
00102 
00103     // get the moab instance for convenience
00104     moab::Interface* moabInstance = mk_core()->moab_instance();
00105 
00106     // query the boundary to find mesh edges
00107     // Note: the senses returned by this method should be either FORWARD
00108     //   or REVERSE, not BOTH . . .
00109     //   but I think there is a chance that mesh edges that are on a
00110     //   geometric edge that has a sense of BOTH might not agree with
00111     //   nearby edges and thus might not form a wire when placed end
00112     //   to end.  The AF2Algorithm doesn't require that the input be in
00113     //   wire order, and should be okay as long as the edge actually
00114     //   does appear with both senses.
00115     std::vector<moab::EntityHandle> bndryEdges;
00116     std::vector<int> bEdgeSenses;
00117     modelEnt->boundary(1, bndryEdges, &bEdgeSenses);
00118 
00119     // get lists of the vertex coordinates and handles
00120     // along with an index from the edge handles into those lists
00121     std::vector<int> bndryIds;
00122     std::vector<double> coords;
00123     moab::Range bndryVertsRange;
00124     modelEnt->get_indexed_connect_coords(
00125         bndryEdges, &bEdgeSenses, NULL, bndryIds, coords, &bndryVertsRange);
00126     std::vector<moab::EntityHandle> bndryVertsVec(
00127         bndryVertsRange.begin(), bndryVertsRange.end());
00128 
00129     // convert the edges into the unsigned int format that is needed for
00130     // input into the AF2Algorithm
00131     // Note: The tags used inside get_indexed_connect_coords are actually
00132     // unsigned int (as of May 2016)
00133     std::vector<unsigned int> inputEdges;
00134     for (std::vector<int>::const_iterator bidItr = bndryIds.begin();
00135         bidItr != bndryIds.end(); ++bidItr)
00136     {
00137       inputEdges.push_back(*bidItr);
00138     }
00139 
00140     // determine the number of boundary edges and vertices
00141     unsigned int numVertices = bndryVertsVec.size();
00142     unsigned int numEdges = inputEdges.size() / 2;
00143 
00144     // check that there is reasonable data to initialize the front
00145     if (numEdges <= 0)
00146     {
00147       Error failErr(MeshKit::MK_FAILURE);
00148       failErr.set_string("There are no boundary mesh edges to use to initialize the advancing front in AF2DfltTriangleMeshOp.");
00149       throw failErr;
00150     }
00151     // This should never happen if there are edges, but as a sanity check
00152     // since the coordinates of the first vertex may be used to check sizing
00153     if (numVertices <= 0)
00154     {
00155       Error failErr(MeshKit::MK_FAILURE);
00156       failErr.set_string(
00157           "No boundary vertices found in AF2DfltTriangleMeshOp.");
00158       throw failErr;
00159     }
00160 
00161     // configure the sizing function, if any, that will be used
00162     SizingFunction* sizing = NULL;
00163     if (modelEnt->sizing_function_index() > -1)
00164     {
00165       int sfIndex = modelEnt->sizing_function_index();
00166       SizingFunction* tempSizing = mk_core()->sizing_function(sfIndex);
00167       // check the desired size at the coordinates of the first vertex
00168       if (tempSizing->size(&coords[0]) > 0)
00169       {
00170         sizing = tempSizing;
00171       }
00172     }
00173 
00174     // construct the local transform maker and run the algorithm
00175     AF2DfltPlaneProjMaker localTransformMaker(
00176         modelEnt->igeom_instance(), modelEnt->geom_handle(), sizing);
00177 
00178     AF2AlgorithmResult* meshResult = algorithm.execute(&localTransformMaker,
00179         &coords[0], numVertices, &inputEdges[0], numEdges, &bndryVertsVec[0], debug);
00180 
00181     // throw failure if the algorithm did not succeed
00182     if (!meshResult->isSuccessful())
00183     {
00184       delete meshResult;
00185       Error failErr(MeshKit::MK_FAILURE);
00186       failErr.set_string("AF2DfltTriangleMeshOp failed.");
00187       throw failErr;
00188     }
00189 
00190     // Collect the new points in a vector
00191     const std::list<AF2Point3D*>* pointList = meshResult->getPoints();
00192     std::vector<double> newPointCoords;
00193     typedef std::list<AF2Point3D*>::const_iterator ConstPointItr;
00194     int numNewPoints = 0;
00195     for (ConstPointItr pItr = pointList->begin();
00196         pItr != pointList->end(); ++pItr)
00197     {
00198       if (!(*pItr)->isCommitted())
00199       {
00200         ++numNewPoints;
00201         newPointCoords.push_back((*pItr)->getX());
00202         newPointCoords.push_back((*pItr)->getY());
00203         newPointCoords.push_back((*pItr)->getZ());
00204       }
00205     }
00206     // Commit the new points to MOAB
00207     moab::Range newPointsRange;
00208     moabInstance->create_vertices(
00209         &newPointCoords[0], numNewPoints, newPointsRange);
00210     // Set the MOAB handles for the now-committed vertices
00211     ConstPointItr np3dItr = pointList->begin();
00212     for (moab::Range::const_iterator nphItr = newPointsRange.begin();
00213         nphItr != newPointsRange.end(); ++nphItr)
00214     {
00215       while ((*np3dItr)->isCommitted())
00216       {
00217         ++np3dItr;
00218       }
00219       (*np3dItr)->setCommittedHandle(*nphItr);
00220       ++np3dItr;
00221     }
00222 
00223     // get a pointer to the list of new triangles and check how many there are
00224     const std::list<const AF2Polygon3D*>* faceList = meshResult->getFaces();
00225     int numTriangles = faceList->size();
00226 
00227     // pre-allocate connectivity memory to store the triangles
00228     moab::ReadUtilIface* readInterface;
00229     moab::ErrorCode moabRet;
00230     moabRet = moabInstance->query_interface(readInterface);
00231     MBERRCHK(moabRet, moabInstance);
00232     moab::EntityHandle firstHandle;
00233     moab::EntityHandle* triConnectAry;
00234     moabRet = readInterface->get_element_connect(
00235         numTriangles, 3, moab::MBTRI, 0, firstHandle, triConnectAry);
00236     MBERRCHK(moabRet, moabInstance);
00237 
00238     // fill the connectivity array
00239     unsigned int caIndex = 0u;
00240     typedef std::list<const AF2Polygon3D*>::const_iterator ConstTriangleItr;
00241     for (ConstTriangleItr tItr = faceList->begin();
00242         tItr != faceList->end(); ++tItr)
00243     {
00244       for (unsigned int vi = 0; vi < 3; ++vi)
00245       {
00246         triConnectAry[caIndex + vi] = (*tItr)->getVertex(vi)->getVertexHandle();
00247       }
00248       caIndex += 3;
00249     }
00250 
00251     delete meshResult;
00252 
00253     // Insert the new entities into the entity range
00254     selIt->second.insert(firstHandle, firstHandle + numTriangles - 1);
00255 
00256     // Commit the mesh
00257     modelEnt->commit_mesh(selIt->second, COMPLETE_MESH);
00258   }
00259 }
00260 
00261 const moab::EntityType* AF2DfltTriangleMeshOp::mesh_types_arr() const
00262 {
00263   return output_types();
00264 }
00265 
00266 void AF2DfltTriangleMeshOp::setup_this()
00267 {
00268   // Check that the dimension is correct for each model entity and pass
00269   // down the sizing functions that are set on the selected surfaces
00270   // to their boundary edges if those edges don't have sizing functions set
00271   for (MEntSelection::iterator selIt = mentSelection.begin();
00272       selIt != mentSelection.end(); ++selIt)
00273   {
00274     // extract the model entity from the map iterator
00275     ModelEnt* modelEnt = selIt->first;
00276 
00277     // check that the dimension of the selected model entity is two
00278     if (modelEnt->dimension() != 2)
00279     {
00280       Error dimErr(MeshKit::MK_WRONG_DIMENSION);
00281       dimErr.set_string("Found a selected entity of dimension not equal to 2 in AF2DfltTriangleMeshOp.");
00282       throw dimErr;
00283     }
00284 
00285     // Try to check whether there is a valid sizing function set on the
00286     // model entity.
00287     int sFIndex = -1;
00288     if (modelEnt->sizing_function_index() > -1)
00289     {
00290       int tempSFIndex = modelEnt->sizing_function_index();
00291       SizingFunction* tempSizing = mk_core()->sizing_function(tempSFIndex);
00292       // check the desired size at the coordinates of the first vertex
00293       if (tempSizing->size() > 0)
00294       {
00295         sFIndex = tempSFIndex;
00296       }
00297     }
00298 
00299     // If the sizing function appears to be valid, pass it down to adjacent
00300     // children that do not have a sizing function set, because it is best
00301     // to have the size on the boundaries about right.
00302     if (sFIndex > -1)
00303     {
00304       MEntVector bndryEdges;
00305       modelEnt->get_adjacencies(1, bndryEdges);
00306       for (MEntVector::iterator beItr = bndryEdges.begin();
00307           beItr != bndryEdges.end(); ++beItr)
00308       {
00309         int beSFIndex = (*beItr)->sizing_function_index();
00310         if (beSFIndex == -1)
00311         {
00312           (*beItr)->sizing_function_index(sFIndex);
00313         }
00314       }
00315     }
00316   }
00317 
00318   // Set up the default MeshOp on any children that need one
00319   setup_boundary();
00320 
00321   // Make sure that this MeshOp depends on all MeshOps set on its facets
00322   ensure_facet_dependencies(false);
00323 }
00324 
00325 } // namespace MeshKit
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines