MeshKit  1.0
AF2Algorithm.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines