void BSplineCurveEvaluator::evaluateCurve(const std::vector<Point>& ptvCtrlPts, 
										 std::vector<Point>& ptvEvaluatedCurvePts, 
										 const float& fAniLength, 
										 const bool& bWrap) const
{
	ptvEvaluatedCurvePts.clear();
    std::vector<double> samplePoints(_numSamples + 1,_numSamples);
    ufGenSample uf;
    std::transform(samplePoints.begin(),samplePoints.end(),samplePoints.begin(),uf);

    // if wrapping is off, make the first and last segments of
    // the curve horizontal.
    Mat4d basisMat(1.0f/6.0f,-1.0f/2.0f,1.0f/2.0f,-1.0f/6.0f,2.0f/3.0f,0.0f,-1.0f,1.0f/2.0f,1.0f/6.0f,1.0f/2.0f,1.0f/2.0f,-1.0f/2.0f,0.0f,0.0f,0.0f,1.0f/6.0f);

    std::vector<Point> knotVector;
    if(~bWrap){
        knotVector.push_back(ptvCtrlPts[0]);
        knotVector.push_back(ptvCtrlPts[0]);}
    for(std::vector<Point>::const_iterator itC = ptvCtrlPts.begin(); itC!=ptvCtrlPts.end();++itC)
        knotVector.push_back(*itC);
    if(bWrap){
        knotVector.push_back(*(ptvCtrlPts.end() - 1));
        knotVector.push_back(Point(fAniLength + ptvCtrlPts[0].x, ptvCtrlPts[0].y));
        knotVector.push_back(Point(fAniLength + ptvCtrlPts[0].x, ptvCtrlPts[0].y));}


    if(~bWrap){
        knotVector.push_back(*(ptvCtrlPts.end() - 1));
        knotVector.push_back(*(ptvCtrlPts.end() - 1));}

    for(std::vector<Point>::iterator it = knotVector.begin();it!=(knotVector.end()-3);++it){
        Point P0 = *it;
        Point P1 = *(1 + it);
        Point P2 = *(2 + it);
        Point P3 = *(3 + it);
        for(std::vector<double>::iterator it = samplePoints.begin();it!=samplePoints.end();++it){
            Vec4d sampleMultVec(1,*it,(*it) * (*it), (*it) * (*it) * (*it));
            Vec4d result = basisMat * sampleMultVec;
            Point evalPt = (result[0]*P0) + (result[1]*P1) + (result[2]*P2) + (result[3]*P3);
            if(bWrap){
                if(evalPt.x>fAniLength){
                    evalPt.x-=fAniLength;
                    if(evalPt.x>ptvCtrlPts[0].x)
                        continue;}}
            ptvEvaluatedCurvePts.push_back(evalPt);
        }
    }
    if(!bWrap){
        ptvEvaluatedCurvePts.push_back(Point(0.0f,ptvCtrlPts[0].y));
        ptvEvaluatedCurvePts.push_back(Point(fAniLength,(*(ptvCtrlPts.end() -1)).y));
    }
}
void Foam::timeVaryingMappedFixedValuePointPatchField<Type>::checkTable()
{
    // Initialise
    if (startSampleTime_ == -1 && endSampleTime_ == -1)
    {
        const polyMesh& pMesh = this->patch().boundaryMesh().mesh()();

        // Read the initial point position
        pointField meshPts;

        if (pMesh.pointsInstance() == pMesh.facesInstance())
        {
            meshPts = pointField(pMesh.points(), this->patch().meshPoints());
        }
        else
        {
            // Load points from facesInstance
            if (debug)
            {
                Info<< "Reloading points0 from " << pMesh.facesInstance()
                    << endl;
            }

            pointIOField points0
            (
                IOobject
                (
                    "points",
                    pMesh.facesInstance(),
                    polyMesh::meshSubDir,
                    pMesh,
                    IOobject::MUST_READ,
                    IOobject::NO_WRITE,
                    false
                )
            );
            meshPts = pointField(points0, this->patch().meshPoints());
        }

        pointIOField samplePoints
        (
            IOobject
            (
                "points",
                this->db().time().constant(),
                "boundaryData"/this->patch().name(),
                this->db(),
                IOobject::MUST_READ,
                IOobject::AUTO_WRITE,
                false
            )
        );

        // tbd: run-time selection
        bool nearestOnly =
        (
           !mapMethod_.empty()
         && mapMethod_ != "planarInterpolation"
        );

        // Allocate the interpolator
        mapperPtr_.reset
        (
            new pointToPointPlanarInterpolation
            (
                samplePoints,
                meshPts,
                perturb_,
                nearestOnly
            )
        );

        // Read the times for which data is available

        const fileName samplePointsFile = samplePoints.filePath();
        const fileName samplePointsDir = samplePointsFile.path();
        sampleTimes_ = Time::findTimes(samplePointsDir);

        if (debug)
        {
            Info<< "timeVaryingMappedFixedValuePointPatchField : In directory "
                << samplePointsDir << " found times "
                << pointToPointPlanarInterpolation::timeNames(sampleTimes_)
                << endl;
        }
    }

    // Find current time in sampleTimes
    label lo = -1;
    label hi = -1;

    bool foundTime = mapperPtr_().findTime
    (
        sampleTimes_,
        startSampleTime_,
        this->db().time().value(),
        lo,
        hi
    );

    if (!foundTime)
    {
        FatalErrorIn
        (
            "timeVaryingMappedFixedValuePointPatchField<Type>::checkTable"
        )   << "Cannot find starting sampling values for current time "
            << this->db().time().value() << nl
            << "Have sampling values for times "
            << pointToPointPlanarInterpolation::timeNames(sampleTimes_) << nl
            << "In directory "
            <<  this->db().time().constant()/"boundaryData"/this->patch().name()
            << "\n    on patch " << this->patch().name()
            << " of field " << fieldTableName_
            << exit(FatalError);
    }


    // Update sampled data fields.

    if (lo != startSampleTime_)
    {
        startSampleTime_ = lo;

        if (startSampleTime_ == endSampleTime_)
        {
            // No need to reread since are end values
            if (debug)
            {
                Pout<< "checkTable : Setting startValues to (already read) "
                    <<   "boundaryData"
                        /this->patch().name()
                        /sampleTimes_[startSampleTime_].name()
                    << endl;
            }
            startSampledValues_ = endSampledValues_;
            startAverage_ = endAverage_;
        }
        else
        {
            if (debug)
            {
                Pout<< "checkTable : Reading startValues from "
                    <<   "boundaryData"
                        /this->patch().name()
                        /sampleTimes_[lo].name()
                    << endl;
            }

            // Reread values and interpolate
            AverageIOField<Type> vals
            (
                IOobject
                (
                    fieldTableName_,
                    this->db().time().constant(),
                    "boundaryData"
                   /this->patch().name()
                   /sampleTimes_[startSampleTime_].name(),
                    this->db(),
                    IOobject::MUST_READ,
                    IOobject::AUTO_WRITE,
                    false
                )
            );

            if (vals.size() != mapperPtr_().sourceSize())
            {
                FatalErrorIn
                (
                    "timeVaryingMappedFixedValuePointPatchField<Type>::"
                    "checkTable()"
                )   << "Number of values (" << vals.size()
                    << ") differs from the number of points ("
                    <<  mapperPtr_().sourceSize()
                    << ") in file " << vals.objectPath() << exit(FatalError);
            }

            startAverage_ = vals.average();
            startSampledValues_ = mapperPtr_().interpolate(vals);
        }
    }

    if (hi != endSampleTime_)
    {
        endSampleTime_ = hi;

        if (endSampleTime_ == -1)
        {
            // endTime no longer valid. Might as well clear endValues.
            if (debug)
            {
                Pout<< "checkTable : Clearing endValues" << endl;
            }
            endSampledValues_.clear();
        }
        else
        {
            if (debug)
            {
                Pout<< "checkTable : Reading endValues from "
                    <<   "boundaryData"
                        /this->patch().name()
                        /sampleTimes_[endSampleTime_].name()
                    << endl;
            }
            // Reread values and interpolate
            AverageIOField<Type> vals
            (
                IOobject
                (
                    fieldTableName_,
                    this->db().time().constant(),
                    "boundaryData"
                   /this->patch().name()
                   /sampleTimes_[endSampleTime_].name(),
                    this->db(),
                    IOobject::MUST_READ,
                    IOobject::AUTO_WRITE,
                    false
                )
            );

            if (vals.size() != mapperPtr_().sourceSize())
            {
                FatalErrorIn
                (
                    "timeVaryingMappedFixedValuePointPatchField<Type>::"
                    "checkTable()"
                )   << "Number of values (" << vals.size()
                    << ") differs from the number of points ("
                    <<  mapperPtr_().sourceSize()
                    << ") in file " << vals.objectPath() << exit(FatalError);
            }

            endAverage_ = vals.average();
            endSampledValues_ = mapperPtr_().interpolate(vals);
        }
    }
}
void BSplineSurfaceFitterWindow::CreateScene()
{
    // Begin with a flat 64x64 height field.
    int const numSamples = 64;
    float const extent = 8.0f;
    VertexFormat hfformat;
    hfformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    hfformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    MeshFactory mf;
    mf.SetVertexFormat(hfformat);
    mHeightField = mf.CreateRectangle(numSamples, numSamples, extent, extent);
    int numVertices = numSamples * numSamples;
    VertexPT* hfvertices = mHeightField->GetVertexBuffer()->Get<VertexPT>();

    // Set the heights based on a precomputed height field.  Also create a
    // texture image to go with the height field.
    std::string path = mEnvironment.GetPath("BTHeightField.png");
    std::shared_ptr<Texture2> texture(WICFileIO::Load(path, false));
    std::shared_ptr<Texture2Effect> txeffect =
        std::make_shared<Texture2Effect>(mProgramFactory, texture,
        SamplerState::MIN_L_MAG_L_MIP_P, SamplerState::CLAMP,
        SamplerState::CLAMP);
    mHeightField->SetEffect(txeffect);

    std::mt19937 mte;
    std::uniform_real_distribution<float> symmr(-0.05f, 0.05f);
    std::uniform_real_distribution<float> intvr(32.0f, 64.0f);
    unsigned char* data = (unsigned char*)texture->Get<unsigned char>();
    std::vector<Vector3<float>> samplePoints(numVertices);
    for (int i = 0; i < numVertices; ++i)
    {
        unsigned char value = *data;
        float height = 3.0f*((float)value) / 255.0f + symmr(mte);
        *data++ = (unsigned char)intvr(mte);
        *data++ = 3 * (128 - value / 2) / 4;
        *data++ = 0;
        data++;

        hfvertices[i].position[2] = height;
        samplePoints[i] = hfvertices[i].position;
    }

    // Compute a B-Spline surface with NxN control points, where N < 64.
    // This surface will be sampled to 64x64 and displayed together with the
    // original height field for comparison.
    int const numControls = 32;
    int const degree = 3;
    BSplineSurfaceFit<float> fitter(degree, numControls, numSamples, degree,
        numControls, numSamples, &samplePoints[0]);

    VertexFormat ffformat;
    ffformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    ffformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0);
    mf.SetVertexFormat(ffformat);
    mFittedField = mf.CreateRectangle(numSamples, numSamples, extent, extent);
    VertexPC* ffvertices = mFittedField->GetVertexBuffer()->Get<VertexPC>();

    Vector4<float> translucent{ 1.0f, 1.0f, 1.0f, 0.5f };
    for (int i = 0; i < numVertices; ++i)
    {
        float u = 0.5f*(ffvertices[i].position[0] / extent + 1.0f);
        float v = 0.5f*(ffvertices[i].position[1] / extent + 1.0f);
        ffvertices[i].position = fitter.GetPosition(u, v);
        ffvertices[i].color = translucent;
    }

    std::shared_ptr<VertexColorEffect> vceffect =
        std::make_shared<VertexColorEffect>(mProgramFactory);
    mFittedField->SetEffect(vceffect);

    mCameraRig.Subscribe(mHeightField->worldTransform,
        txeffect->GetPVWMatrixConstant());
    mCameraRig.Subscribe(mFittedField->worldTransform,
        vceffect->GetPVWMatrixConstant());

    mTrackball.Attach(mHeightField);
    mTrackball.Attach(mFittedField);
    mTrackball.Update();
}
void timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()
{
    // Read the sample points

    pointIOField samplePoints
    (
        IOobject
        (
            "points",
            this->db().time().constant(),
            "boundaryData"/this->patch().name(),
            this->db(),
            IOobject::MUST_READ,
            IOobject::AUTO_WRITE,
            false
        )
    );

    const fileName samplePointsFile = samplePoints.filePath();

    if (debug)
    {
        Info<< "timeVaryingMappedFixedValueFvPatchField :"
            << " Read " << samplePoints.size() << " sample points from "
            << samplePointsFile << endl;
    }

    // Determine coordinate system from samplePoints

    if (samplePoints.size() < 3)
    {
        FatalErrorIn
        (
            "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
        )   << "Only " << samplePoints.size() << " points read from file "
            << samplePoints.objectPath() << nl
            << "Need at least three non-colinear samplePoints"
            << " to be able to interpolate."
            << "\n    on patch " << this->patch().name()
            << " of field " << this->dimensionedInternalField().name()
            << " in file " << this->dimensionedInternalField().objectPath()
            << exit(FatalError);
    }

    const point& p0 = samplePoints[0];

    // Find point separate from p0
    vector e1;
    label index1 = -1;

    for (label i = 1; i < samplePoints.size(); i++)
    {
        e1 = samplePoints[i] - p0;

        scalar magE1 = mag(e1);

        if (magE1 > SMALL)
        {
            e1 /= magE1;
            index1 = i;
            break;
        }
    }

    // Find point that makes angle with n1
    label index2 = -1;
    vector e2;
    vector n;

    for (label i = index1+1; i < samplePoints.size(); i++)
    {
        e2 = samplePoints[i] - p0;

        scalar magE2 = mag(e2);

        if (magE2 > SMALL)
        {
            e2 /= magE2;

            n = e1^e2;

            scalar magN = mag(n);

            if (magN > SMALL)
            {
                index2 = i;
                n /= magN;
                break;
            }
        }
    }

    if (index2 == -1)
    {
        FatalErrorIn
        (
            "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
        )   << "Cannot find points that make valid normal." << nl
            << "Need at least three sample points which are not in a line."
            << "\n    on patch " << this->patch().name()
            << " of field " << this->dimensionedInternalField().name()
            << " in file " << this->dimensionedInternalField().objectPath()
            << exit(FatalError);
    }

    if (debug)
    {
        Info<< "timeVaryingMappedFixedValueFvPatchField :"
            << " Used points " << p0 << ' ' << samplePoints[index1]
            << ' ' << samplePoints[index2]
            << " to define coordinate system with normal " << n << endl;
    }

    referenceCS_.reset
    (
        new cartesianCS
        (
            "reference",
            p0,             // origin
            n,              // normal
            e1              // 0-axis
        )
    );

    tmp<vectorField> tlocalVertices
    (
        referenceCS().localPosition(samplePoints)
    );
    const vectorField& localVertices = tlocalVertices();

    // Determine triangulation
    List<vector2D> localVertices2D(localVertices.size());
    forAll(localVertices, i)
    {
        localVertices2D[i][0] = localVertices[i][0];
        localVertices2D[i][1] = localVertices[i][1];
    }
void timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()
{
    // Read the sample points

    pointIOField samplePoints
    (
        IOobject
        (
            "points",
            this->db().time().constant(),
            "boundaryData"/this->patch().name(),
            this->db(),
            IOobject::MUST_READ,
            IOobject::AUTO_WRITE,
            false
        )
    );

    const fileName samplePointsFile = samplePoints.filePath();

    if (debug)
    {
        Info<< "timeVaryingMappedFixedValueFvPatchField :"
            << " Read " << samplePoints.size() << " sample points from "
            << samplePointsFile << endl;
    }

    // Determine coordinate system from samplePoints

    if (samplePoints.size() < 3)
    {
        FatalErrorIn
        (
            "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
        )   << "Only " << samplePoints.size() << " points read from file "
            << samplePoints.objectPath() << nl
            << "Need at least three non-colinear samplePoints"
            << " to be able to interpolate."
            << "\n    on patch " << this->patch().name()
            << " of points " << samplePoints.name()
            << " in file " << samplePoints.objectPath()
            << exit(FatalError);
    }

    const point& p0 = samplePoints[0];

    // Find furthest away point
    vector e1;
    label index1 = -1;
    scalar maxDist = -GREAT;

    for (label i = 1; i < samplePoints.size(); i++)
    {
        const vector d = samplePoints[i] - p0;
        scalar magD = mag(d);

        if (magD > maxDist)
        {
            e1 = d/magD;
            index1 = i;
            maxDist = magD;
        }
    }
    // Find point that is furthest away from line p0-p1
    const point& p1 = samplePoints[index1];

    label index2 = -1;
    maxDist = -GREAT;
    for (label i = 1; i < samplePoints.size(); i++)
    {
        if (i != index1)
        {
            const point& p2 = samplePoints[i];
            vector e2(p2 - p0);
            e2 -= (e2&e1)*e1;
            scalar magE2 = mag(e2);

            if (magE2 > maxDist)
            {
                index2 = i;
                maxDist = magE2;
            }
        }
    }
    if (index2 == -1)
    {
        FatalErrorIn
        (
            "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
        )   << "Cannot find points that make valid normal." << nl
            << "Have so far points " << p0 << " and " << p1
            << "Need at least three sample points which are not in a line."
            << "\n    on patch " << this->patch().name()
            << " of points " << samplePoints.name()
            << " in file " << samplePoints.objectPath()
            << exit(FatalError);
    }

    vector n = e1^(samplePoints[index2]-p0);
    n /= mag(n);

    if (debug)
    {
        Info<< "timeVaryingMappedFixedValueFvPatchField :"
            << " Used points " << p0 << ' ' << samplePoints[index1]
            << ' ' << samplePoints[index2]
            << " to define coordinate system with normal " << n << endl;
    }

    referenceCS_.reset
    (
        new coordinateSystem
        (
            "reference",
            p0,  // origin
            n,   // normal
            e1   // 0-axis
        )
    );

    tmp<vectorField> tlocalVertices
    (
        referenceCS().localPosition(samplePoints)
    );
    vectorField& localVertices = tlocalVertices();

    const boundBox bb(localVertices, true);
    const point bbMid(bb.midpoint());

    if (debug)
    {
        Info<< "timeVaryingMappedFixedValueFvPatchField :"
            << " Perturbing points with " << perturb_
            << " fraction of a random position inside " << bb
            << " to break any ties on regular meshes."
            << nl << endl;
    }

    Random rndGen(123456);
    forAll(localVertices, i)
    {
        localVertices[i] +=
            perturb_
           *(rndGen.position(bb.min(), bb.max())-bbMid);
    }