MeshKit  1.0
AF2DfltRuleAppVisitor.cpp
Go to the documentation of this file.
00001 #include "meshkit/AF2DfltRuleAppVisitor.hpp"
00002 
00003 // C++
00004 #include <cmath>
00005 #include <cstddef>
00006 
00007 // MeshKit
00008 #include "meshkit/Error.hpp"
00009 
00010 const double AF2DfltRuleAppVisitor::eqTriAreaPerimSqRatio = sqrt(3.0) / 36.0;
00011 
00012 AF2DfltRuleAppVisitor::AF2DfltRuleAppVisitor() :
00013     bestMetricVal(0), bestRuleApp(NULL)
00014 {
00015 }
00016 
00017 AF2DfltRuleAppVisitor::~AF2DfltRuleAppVisitor()
00018 {
00019   if (bestRuleApp != NULL)
00020   {
00021     delete bestRuleApp;
00022   }
00023 }
00024 
00025 AF2DfltRuleAppVisitor::AF2DfltRuleAppVisitor(
00026     const AF2DfltRuleAppVisitor & toCopy) :
00027     bestMetricVal(toCopy.bestMetricVal)
00028 {
00029   if (toCopy.bestRuleApp != NULL)
00030   {
00031     bestRuleApp = new AF2RuleApplication(*(toCopy.bestRuleApp));
00032   }
00033 }
00034 
00035 AF2DfltRuleAppVisitor& AF2DfltRuleAppVisitor::operator=(
00036     const AF2DfltRuleAppVisitor & rhs)
00037 {
00038   bestMetricVal = rhs.bestMetricVal;
00039 
00040   if (bestRuleApp == NULL)
00041   {
00042     if (rhs.bestRuleApp != NULL)
00043     {
00044       bestRuleApp = new AF2RuleApplication(*(rhs.bestRuleApp));
00045     }
00046   }
00047   else
00048   {
00049     AF2RuleApplication* tempBestRuleApp = NULL;
00050     if (rhs.bestRuleApp != NULL)
00051     {
00052       tempBestRuleApp = new AF2RuleApplication(*(rhs.bestRuleApp));
00053     }
00054     delete bestRuleApp;
00055     bestRuleApp = tempBestRuleApp;
00056   }
00057 
00058   return *this;
00059 }
00060 
00061 const AF2RuleApplication* AF2DfltRuleAppVisitor::getBestRuleApplication() const
00062 {
00063   return bestRuleApp;
00064 }
00065 
00066 void AF2DfltRuleAppVisitor::visit(AF2RuleApplication const & ruleApp)
00067 {
00068   double metricVal = 0.0;
00069 
00070   // loop over the faces and take the worst face metric value
00071   // as the rule metric value
00072   for (unsigned int faceIndex = 0u;
00073       faceIndex < ruleApp.getNumNewFaces(); ++faceIndex)
00074   {
00075     const AF2Polygon2D* facePtr = ruleApp.getNewFace(faceIndex);
00076 
00077     // verify that the face is a triangle
00078     if (facePtr->getNumVertices() != 3u)
00079     {
00080       MeshKit::Error badArg(MeshKit::MK_BAD_INPUT);
00081       badArg.set_string(
00082           "AF2DfltRuleAppVisitor can visit only triangular faces.");
00083       throw badArg;
00084     }
00085 
00086     // access the vertices of the triangle
00087     const AF2Point2D* faceVtx0 = facePtr->getVertex(0u);
00088     const AF2Point2D* faceVtx1 = facePtr->getVertex(1u);
00089     const AF2Point2D* faceVtx2 = facePtr->getVertex(2u);
00090 
00091     // calculate the components of the vectors along triangle edges
00092     double faceVec01X = faceVtx1->getX() - faceVtx0->getX();
00093     double faceVec01Y = faceVtx1->getY() - faceVtx0->getY();
00094     double faceVec02X = faceVtx2->getX() - faceVtx0->getX();
00095     double faceVec02Y = faceVtx2->getY() - faceVtx0->getY();
00096     double faceVec12X = faceVtx2->getX() - faceVtx1->getX();
00097     double faceVec12Y = faceVtx2->getY() - faceVtx1->getY();
00098 
00099     // calculate the length of each edge from the vector
00100     double sqLen = faceVec01X * faceVec01X + faceVec01Y * faceVec01Y;
00101     double faceVec01Len = sqrt(sqLen);
00102     sqLen = faceVec02X * faceVec02X + faceVec02Y * faceVec02Y;
00103     double faceVec02Len = sqrt(sqLen);
00104     sqLen = faceVec12X * faceVec12X + faceVec12Y * faceVec12Y;
00105     double faceVec12Len = sqrt(sqLen);
00106 
00107     // caculate the perimeter and area
00108     double facePerim = faceVec01Len + faceVec02Len + faceVec12Len;
00109     double faceArea =
00110         0.5 * (faceVec01X * faceVec02Y - faceVec01Y * faceVec02X);
00111     if (faceArea <= 0.0)
00112     {
00113       // the face is inverted, so this rule application is unacceptable
00114       return;
00115     }
00116 
00117     // calculate the face metric value
00118     double faceMetricVal = 10.0 * (eqTriAreaPerimSqRatio *
00119         facePerim * facePerim / faceArea - 1)  + // shape error
00120         1.0/faceVec01Len + faceVec01Len +
00121         1.0/faceVec02Len + faceVec02Len +
00122         1.0/faceVec12Len + faceVec12Len - 6.0; // size error
00123 
00124     // update the rule metric value, if necessary
00125     if (faceMetricVal > metricVal)
00126     {
00127       metricVal = faceMetricVal;
00128     }
00129   }
00130 
00131   // update the best rule application if this is the only rule application
00132   // or is a "measurable" improvement over the previous best
00133   if (bestRuleApp == NULL)
00134   {
00135     bestRuleApp = new AF2RuleApplication(ruleApp);
00136     bestMetricVal = metricVal;
00137   }
00138   else if (metricVal < 0.99*bestMetricVal)
00139   {
00140     *bestRuleApp = ruleApp;
00141     bestMetricVal = metricVal;
00142   }
00143 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines