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