MeshKit
1.0
|
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