bool IntpQdrNonuniform2<Real>::Evaluate (const Vector2<Real>& P, Real& F, Real& FX, Real& FY) { int i = mDT->GetContainingTriangle(P); if (i == -1) { return false; } // Get triangle information. Vector2<Real> V[3]; mDT->GetVertexSet(i, V); int invDet[3]; mDT->GetIndexSet(i, invDet); TriangleData& tData = mTData[i]; // Determine which of the six subtriangles contains the target point. Vector2<Real> sub0 = tData.Center; Vector2<Real> sub1; Vector2<Real> sub2 = tData.Intersect[2]; Real bary[3]; int index; for (index = 1; index <= 6; ++index) { sub1 = sub2; if (index % 2) { sub2 = V[index/2]; } else { sub2 = tData.Intersect[index/2 - 1]; } P.GetBarycentrics(sub0, sub1, sub2, bary); if (bary[0] >= (Real)0 && bary[1] >= (Real)0 && bary[2] >= (Real)0) { // P is in triangle <Sub0,Sub1,Sub2> break; } } // This should not happen theoretically, but it can happen due to // numerical round-off errors. Just in case, select an index and go // with it. Probably better is to keep track of the dot products in // InTriangle and find the one closest to zero and use a triangle that // contains the edge as the one that contains the input point. assertion(index <= 6, "Unexpected condition\n"); if (index > 6) { // Use this index because bary[] was computed last for it. index = 5; } // Fetch Bezier control points. Real bez[6] = { tData.Coeff[0], tData.Coeff[12 + index], tData.Coeff[13 + (index % 6)], tData.Coeff[index], tData.Coeff[6 + index], tData.Coeff[1 + (index % 6)] }; // Evaluate Bezier quadratic. F = bary[0]*(bez[0]*bary[0] + bez[1]*bary[1] + bez[2]*bary[2]) + bary[1]*(bez[1]*bary[0] + bez[3]*bary[1] + bez[4]*bary[2]) + bary[2]*(bez[2]*bary[0] + bez[4]*bary[1] + bez[5]*bary[2]); // Evaluate barycentric derivatives of F. Real FU = ((Real)2.0)*(bez[0]*bary[0] + bez[1]*bary[1] + bez[2]*bary[2]); Real FV = ((Real)2.0)*(bez[1]*bary[0] + bez[3]*bary[1] + bez[4]*bary[2]); Real FW = ((Real)2.0)*(bez[2]*bary[0] + bez[4]*bary[1] + bez[5]*bary[2]); Real duw = FU - FW; Real dvw = FV - FW; // Convert back to (x,y) coordinates. Real m00 = sub0.X() - sub2.X(); Real m10 = sub0.Y() - sub2.Y(); Real m01 = sub1.X() - sub2.X(); Real m11 = sub1.Y() - sub2.Y(); Real inv = ((Real)1)/(m00*m11 - m10*m01); FX = inv*(m11*duw - m10*dvw); FY = inv*(m00*dvw - m01*duw); return true; }