Example #1
0
void ComplexMesh::ImplicitMeanCurvatureFlow(float TimeStep)
{
    Vector<double> VertexAreas(_Vertices.Length());
    Vector<Vec3f> NewVertexPositions(_Vertices.Length());
    NewVertexPositions.Clear(Vec3f::Origin);

    
    SparseMatrix<double> M(_Vertices.Length());

    for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++)
    {
        Vertex &CurVertex = _Vertices[VertexIndex];
        VertexAreas[VertexIndex] = CurVertex.ComputeTriangleArea();
        M.PushElement(VertexIndex, VertexIndex, VertexAreas[VertexIndex]);
        //M.PushElement(VertexIndex, VertexIndex, 1.0f);
        for(UINT EdgeIndex = 0; EdgeIndex < CurVertex.Vertices().Length(); EdgeIndex++)
        {
            Vertex &OtherVertex = *(CurVertex.Vertices()[EdgeIndex]);
            FullEdge &CurEdge = CurVertex.GetSharedEdge(OtherVertex);
            double ConstantFactor = CurEdge.GetCotanTerm() / 4.0f;
            Assert(ConstantFactor == ConstantFactor, "ConstantFactor invalid");
            M.PushElement(VertexIndex, VertexIndex, TimeStep * ConstantFactor);
            M.PushElement(VertexIndex, OtherVertex.Index(), -TimeStep * ConstantFactor);
        }
    }

    BiCGLinearSolver<double> Solver;
    Solver.LoadMatrix(&M);
    const double ErrorTolerance = 1e-6;
    Solver.SetParamaters(1000, ErrorTolerance);
    Solver.Factor();

    for(UINT ElementIndex = 0; ElementIndex < 3; ElementIndex++)
    {
        Vector<double> x, b(_Vertices.Length());
        for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++)
        {
            b[VertexIndex] = _Vertices[VertexIndex].Pos()[ElementIndex] * VertexAreas[VertexIndex];
            //b[VertexIndex] = _Vertices[VertexIndex].Pos().Element(ElementIndex);
        }
        Solver.Solve(x, b);
        Console::WriteLine(Solver.GetOutputString());
        double Error = Solver.ComputeError(x, b);
        Console::WriteLine(String("Mean curvature error: ") + String(Error));
        if(Error < ErrorTolerance)
        {
            for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++)
            {
                NewVertexPositions[VertexIndex][ElementIndex] = float(x[VertexIndex]);
            }
        }
    }

    float AverageDelta = 0.0f;
    for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++)
    {
        Vec3f Delta = NewVertexPositions[VertexIndex] - _Vertices[VertexIndex].Pos();
        AverageDelta += Delta.Length();
    }
    AverageDelta /= _Vertices.Length();
    for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++)
    {
        Vertex &CurVertex = _Vertices[VertexIndex];
        Vec3f Delta = NewVertexPositions[VertexIndex] - _Vertices[VertexIndex].Pos();
        if(Delta.Length() > 2.0f * AverageDelta)
        {
            Delta.SetLength(2.0f * AverageDelta);
        }
        CurVertex.Pos() += Delta;
    }
}
Example #2
0
bool Plane::FitToPoints(const Vector<Vec4f> &Points, Vec3f &Basis1, Vec3f &Basis2, float &NormalEigenvalue, float &ResidualError)
{
    Vec3f Centroid, Normal;

    float ScatterMatrix[3][3];
    int  Order[3];
    float DiagonalMatrix[3];
    float OffDiagonalMatrix[3];

    // Find centroid
    Centroid = Vec3f::Origin;
    float TotalWeight = 0.0f;
    for(UINT i = 0; i < Points.Length(); i++)
    {
        TotalWeight += Points[i].w;
        Centroid += Vec3f(Points[i].x, Points[i].y, Points[i].z) * Points[i].w;
    }
    Centroid /= TotalWeight;

    // Compute scatter matrix
    Find_ScatterMatrix(Points, Centroid, ScatterMatrix, Order);

    tred2(ScatterMatrix,DiagonalMatrix,OffDiagonalMatrix);
    tqli(DiagonalMatrix,OffDiagonalMatrix,ScatterMatrix);

    /*
    **    Find the smallest eigenvalue first.
    */
    float Min = DiagonalMatrix[0];
    float Max = DiagonalMatrix[0];
    UINT MinIndex = 0;
    UINT MiddleIndex = 0;
    UINT MaxIndex = 0;
    for(UINT i = 1; i < 3; i++)
    {
        if(DiagonalMatrix[i] < Min)
        {
            Min = DiagonalMatrix[i];
            MinIndex = i;
        }
        if(DiagonalMatrix[i] > Max)
        {
            Max = DiagonalMatrix[i];
            MaxIndex = i;
        }
    }
    for(UINT i = 0; i < 3; i++)
    {
        if(MinIndex != i && MaxIndex != i)
        {
            MiddleIndex = i;
        }
    }
    /*
    **    The normal of the plane is the smallest eigenvector.
    */
    for(UINT i = 0; i < 3; i++)
    {
        Normal[Order[i]] = ScatterMatrix[i][MinIndex];
        Basis1[Order[i]] = ScatterMatrix[i][MiddleIndex];
        Basis2[Order[i]] = ScatterMatrix[i][MaxIndex];
    }
    NormalEigenvalue = Math::Abs(DiagonalMatrix[MinIndex]);
    Basis1.SetLength(DiagonalMatrix[MiddleIndex]);
    Basis2.SetLength(DiagonalMatrix[MaxIndex]);

    if(!Basis1.Valid() || !Basis2.Valid() || !Normal.Valid())
    {
        *this = ConstructFromPointNormal(Centroid, Vec3f::eX);
        Basis1 = Vec3f::eY;
        Basis2 = Vec3f::eZ;
    }
    else
    {
        *this = ConstructFromPointNormal(Centroid, Normal);
    }

    ResidualError = 0.0f;
    for(UINT i = 0; i < Points.Length(); i++)
    {
        ResidualError += UnsignedDistance(Vec3f(Points[i].x, Points[i].y, Points[i].z));
    }
    ResidualError /= Points.Length();

    return true;
}