コード例 #1
0
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;
}