MeshKit
1.0
|
00001 #include "meshkit/AF2Algorithm.hpp" 00002 00003 // C++ 00004 #include <cstddef> 00005 #include <vector> 00006 #include <map> 00007 00008 // MeshKit 00009 #include "meshkit/AF2DfltRuleAppVisitor.hpp" 00010 #include "meshkit/AF2Edge3D.hpp" 00011 #include "meshkit/AF2RuleApplication.hpp" 00012 #include "meshkit/Error.hpp" 00013 00014 // for debugging 00015 #include <iostream> 00016 00017 AF2Algorithm::AF2Algorithm(const std::list<const AF2Rule*> & ruleListArg) : 00018 ruleList(ruleListArg) 00019 { 00020 // do nothing beyond copying the list of rules in initialization 00021 } 00022 00023 AF2Algorithm::~AF2Algorithm() 00024 { 00025 // do nothing, the standard deletion of the rule list is sufficient, 00026 // since this does not take ownership of the rules 00027 } 00028 00029 AF2Algorithm::AF2Algorithm(const AF2Algorithm & toCopy) 00030 { 00031 // Note: the default implementation would work at this point, but 00032 // might not in the future, and there shouldn't be much need to 00033 // copy this. 00034 MeshKit::Error notImpl(MeshKit::MK_NOT_IMPLEMENTED); 00035 notImpl.set_string("AF2Algorithm copy construction is not supported."); 00036 throw notImpl; 00037 } 00038 00039 AF2Algorithm& AF2Algorithm::operator=(const AF2Algorithm & rhs) 00040 { 00041 // Note: the default implementation would work at this point, but 00042 // might not in the future, and there shouldn't be much need to 00043 // assign this. 00044 MeshKit::Error notImpl(MeshKit::MK_NOT_IMPLEMENTED); 00045 notImpl.set_string("AF2Algorithm assignment operator is not supported."); 00046 throw notImpl; 00047 } 00048 00049 AF2AlgorithmResult* AF2Algorithm::execute( 00050 const AF2LocalTransformMaker* const & transformMaker, 00051 const double* coords, unsigned int numPoints, 00052 const unsigned int* edges, unsigned int numEdges, 00053 const moab::EntityHandle* vertexHandles, int debug) const 00054 { 00055 typedef std::list<const AF2Rule*>::const_iterator RuleConstItr; 00056 00057 // these are used for debugging 00058 static int face=0; 00059 face++; 00060 00061 unsigned long int nextPointId = 0ul; 00062 std::list<AF2Point3D*> allPoints; 00063 std::list<const AF2Polygon3D*> allFaces; 00064 AF2Front front; 00065 00066 // initialize the front 00067 initFront(front, allPoints, nextPointId, 00068 coords, numPoints, edges, numEdges, vertexHandles); 00069 if (debug>1) 00070 { 00071 std::cout<<" On surface " << face << " initial front " << allPoints.size() << " points and " << numEdges << " edges.\n"; 00072 } 00073 int step = 0; 00074 // while the front is not empty and there is still progress 00075 while (!front.isEmpty() && front.getMaximumQuality() < 50u) 00076 { 00077 // select a neighborhood on the advancing front 00078 AF2Neighborhood* ngbhd = front.selectNeighborhood(transformMaker); 00079 AF2Edge3D* baselineEdge = ngbhd->getBaselineEdge3D(); 00080 00081 // attempt to apply each of the rules to the neighborhood 00082 AF2DfltRuleAppVisitor ruleAppVisitor; 00083 for (RuleConstItr itr = ruleList.begin(); itr != ruleList.end(); ++itr) 00084 { 00085 (*itr)->applyRule(*ngbhd, 00086 baselineEdge->getQualityLevel(), ruleAppVisitor); 00087 } 00088 00089 // process the results of attempting to apply rules 00090 const AF2RuleApplication* bestRuleApp = 00091 ruleAppVisitor.getBestRuleApplication(); 00092 if (bestRuleApp == NULL) 00093 { 00094 // there were no successful rule applications, so decrease the quality 00095 baselineEdge->decreaseQuality(); 00096 } 00097 else 00098 { 00099 // there was a successful rule application, so process it and advance 00100 00101 // add any new points added by the rule application 00102 std::map<const AF2Point2D*, AF2Point3D*> newPointsMap; 00103 for (unsigned int npi = 0; npi < bestRuleApp->getNumNewPoints(); ++npi) 00104 { 00105 processNewPoint(bestRuleApp->getNewPoint(npi), nextPointId, 00106 ngbhd, newPointsMap, allPoints, front); 00107 } 00108 00109 // add the faces added by the rule application 00110 for (unsigned int nfi = 0; nfi < bestRuleApp->getNumNewFaces(); ++nfi) 00111 { 00112 processNewFace(bestRuleApp->getNewFace(nfi), 00113 ngbhd, newPointsMap, allFaces, front); 00114 } 00115 // at a successful application, dump the content if we want to 00116 step++; 00117 if (debug>2) 00118 { 00119 output_intermediate_result(allPoints, allFaces, face, step); 00120 } 00121 } 00122 } 00123 00124 if (front.isEmpty()) 00125 { 00126 // the advancing front algorithm successfully completed 00127 if (debug>0) 00128 { 00129 std::cout<<" On surface " << face << " generated " << allPoints.size() << " points and " << allFaces.size() << " triangles\n"; 00130 } 00131 return new AF2AlgorithmResult(allPoints, allFaces); 00132 } 00133 00134 // the advancing front algorithm failed 00135 release(allPoints, allFaces); 00136 return new AF2AlgorithmResult(); 00137 } 00138 00139 void AF2Algorithm::initFront(AF2Front & front, std::list<AF2Point3D*> & pntList, 00140 unsigned long & pntId, 00141 const double* coords, unsigned int numPoints, 00142 const unsigned int* edges, unsigned int numEdges, 00143 const moab::EntityHandle* vertexHandles) const 00144 { 00145 // make the point objects and add them to the front 00146 std::vector<AF2Point3D*> pntVector; 00147 pntVector.reserve(numPoints); 00148 for (unsigned int pi = 0; pi < numPoints; ++pi) 00149 { 00150 AF2Point3D* point = new AF2Point3D(pntId, 00151 coords[3*pi], coords[3*pi + 1], coords[3*pi + 2]); 00152 ++pntId; 00153 if (vertexHandles != NULL) 00154 { 00155 point->setCommittedHandle(vertexHandles[pi]); 00156 } 00157 pntVector.push_back(point); 00158 pntList.push_back(point); 00159 front.addPoint(point); 00160 } 00161 00162 // make the edge objects and gather them in a list of edges 00163 std::list<AF2Edge3D*> edgeList; 00164 for (unsigned int ei = 0; ei < numEdges; ++ei) 00165 { 00166 if (edges[2*ei] >= numPoints || edges[2*ei + 1] >= numPoints) 00167 { 00168 MeshKit::Error badArg(MeshKit::MK_BAD_INPUT); 00169 badArg.set_string("An edge index exceeds the number of points."); 00170 throw badArg; 00171 } 00172 AF2Point3D* edgeStart = pntVector[edges[2*ei]]; 00173 AF2Point3D* edgeEnd = pntVector[edges[2*ei + 1]]; 00174 // mark the endpoints of the edges as on the initial boundary 00175 // Note: This is not done for isolated points, since the front 00176 // does not start to advance from them. 00177 edgeStart->limitDistanceToBoundary(0); 00178 edgeEnd->limitDistanceToBoundary(0); 00179 AF2Edge3D* edge = new AF2Edge3D(edgeStart, edgeEnd); 00180 edgeList.push_back(edge); 00181 } 00182 00183 // initialize the front with the edges 00184 front.advanceFront(edgeList); 00185 } 00186 00187 void AF2Algorithm::processNewFace(const AF2Polygon2D* newFace2D, 00188 AF2Neighborhood* & ngbhd, 00189 std::map<const AF2Point2D*, AF2Point3D*> & newPointsMap, 00190 std::list<const AF2Polygon3D*> & allFaces, AF2Front & front) const 00191 { 00192 std::list<const AF2Point3D*> facePoints3D; 00193 std::list<AF2Edge3D*> edgeList; 00194 00195 AF2Point3D* firstVertex = NULL; 00196 AF2Point3D* prevVertex = NULL; 00197 AF2Point3D* curVertex = NULL; 00198 for (unsigned int fvi = 0; fvi < newFace2D->getNumVertices(); ++fvi) 00199 { 00200 // get the 3-D point corresponding to the 2-D point . . . 00201 const AF2Point2D* faceVertex2D = newFace2D->getVertex(fvi); 00202 // . . . either from the neighborhood . . . 00203 curVertex = ngbhd->getCorrespondingPoint(faceVertex2D); 00204 // . . . or from the map of new points that were added. 00205 if (curVertex == NULL) 00206 { 00207 curVertex = newPointsMap[faceVertex2D]; 00208 } 00209 00210 // add it to the list of points for future creation of the 3-D face 00211 facePoints3D.push_back(curVertex); 00212 00213 // process the edge 00214 if (firstVertex == NULL) 00215 { 00216 // at the first vertex just store the first vertex and what will be 00217 // the previous vertex 00218 firstVertex = curVertex; 00219 prevVertex = curVertex; 00220 } 00221 else 00222 { 00223 // create and store an edge from the current to the previous vertex 00224 edgeList.push_back(new AF2Edge3D(curVertex, prevVertex)); 00225 // update what will be the previous vertex 00226 prevVertex = curVertex; 00227 } 00228 } 00229 // create and store an edge from the first vertex to the last vertex 00230 edgeList.push_back(new AF2Edge3D(firstVertex, curVertex)); 00231 00232 // create the three-dimensional face and add it to the list of faces 00233 allFaces.push_back(new AF2Polygon3D(facePoints3D)); 00234 00235 // advance the front with the edges 00236 front.advanceFront(edgeList); 00237 } 00238 00239 void AF2Algorithm::processNewPoint(const AF2Point2D* newPoint2D, 00240 unsigned long & pntId, 00241 AF2Neighborhood* & ngbhd, 00242 std::map<const AF2Point2D*, AF2Point3D*> & newPointsMap, 00243 std::list<AF2Point3D*> & allPoints, AF2Front & front) const 00244 { 00245 AF2Point3D* newPoint3D = ngbhd->transformPoint(newPoint2D, pntId); 00246 ++pntId; 00247 newPointsMap[newPoint2D] = newPoint3D; 00248 allPoints.push_back(newPoint3D); 00249 front.addPoint(newPoint3D); 00250 } 00251 00252 void AF2Algorithm::release(std::list<AF2Point3D*> & allPoints, 00253 std::list<const AF2Polygon3D*> & allFaces) const 00254 { 00255 typedef std::list<const AF2Polygon3D*>::iterator FaceItr; 00256 typedef std::list<AF2Point3D*>::iterator PointItr; 00257 00258 for (FaceItr itr = allFaces.begin(); itr != allFaces.end(); ++itr) 00259 { 00260 delete (*itr); 00261 } 00262 00263 for (PointItr itr = allPoints.begin(); itr != allPoints.end(); ++itr) 00264 { 00265 delete (*itr); 00266 } 00267 } 00268 00269 #include "moab/Core.hpp" 00270 #include "moab/ReadUtilIface.hpp" 00271 void AF2Algorithm::output_intermediate_result (std::list<AF2Point3D*> & allPoints, 00272 std::list<const AF2Polygon3D*> & allFaces,int face, int step) const 00273 { 00274 moab::Core mb; 00275 int num_nodes = (int) allPoints.size(); 00276 std::vector<double> newPointCoords; 00277 typedef std::list<AF2Point3D*>::const_iterator ConstPointItr; 00278 for (ConstPointItr pItr = allPoints.begin(); 00279 pItr != allPoints.end(); ++pItr) 00280 { 00281 newPointCoords.push_back((*pItr)->getX()); 00282 newPointCoords.push_back((*pItr)->getY()); 00283 newPointCoords.push_back((*pItr)->getZ()); 00284 } 00285 // Commit the new points to MOAB 00286 moab::Range newPointsRange; 00287 mb.create_vertices( 00288 &newPointCoords[0], num_nodes, newPointsRange); 00289 // Set the map between local ID and moab handle 00290 std::map<long, moab::EntityHandle> idToHandle; 00291 ConstPointItr np3dItr = allPoints.begin(); 00292 for (moab::Range::const_iterator nphItr = newPointsRange.begin(); 00293 nphItr != newPointsRange.end(); ++nphItr) 00294 { 00295 00296 long localID = (*np3dItr)->getLocalId(); 00297 idToHandle[localID]=*nphItr; 00298 ++np3dItr; 00299 } 00300 00301 int numTriangles = allFaces.size(); 00302 00303 // pre-allocate connectivity memory to store the triangles 00304 moab::ReadUtilIface* readInterface; 00305 mb.query_interface(readInterface); 00306 00307 moab::EntityHandle firstHandle; 00308 moab::EntityHandle* triConnectAry; 00309 readInterface->get_element_connect( 00310 numTriangles, 3, moab::MBTRI, 0, firstHandle, triConnectAry); 00311 00312 unsigned int caIndex = 0u; 00313 typedef std::list<const AF2Polygon3D*>::const_iterator ConstTriangleItr; 00314 for (ConstTriangleItr tItr = allFaces.begin(); 00315 tItr != allFaces.end(); ++tItr) 00316 { 00317 for (unsigned int vi = 0; vi < 3; ++vi) 00318 { 00319 triConnectAry[caIndex + vi] = idToHandle[(*tItr)->getVertex(vi)->getLocalId()]; 00320 } 00321 caIndex += 3; 00322 } 00323 00324 std::stringstream tempStep; 00325 tempStep<<"Face_"<< face << "_Step" <<step<< ".vtk"; 00326 mb.write_file(tempStep.str().c_str()); 00327 00328 00329 return; 00330 } 00331